---
# System prepended metadata

title: package
tags: [Go]

---

## 
![](https://hackmd.io/_uploads/SywDTAuo3.png)


https://github.com/zc2638/go-standard
## math

### MulUintptr
計算是不是越界


## url
https://juejin.cn/post/7262293451755618360


## uintptr和unsafe.Pointer


## Bytes Buffer 
https://www.youtube.com/watch?v=ENxfg9rS5dc&ab_channel=AnthonyGG
簡單來說defer close 部分放在wire那邊

## 爬蟲
https://juejin.cn/post/7285576848237559843

## proto json
![](https://hackmd.io/_uploads/HJkq29Ei3.png)


# package

## http
https://cizixs.com/2016/08/17/golang-http-server-side/
https://zhuanlan.zhihu.com/p/609258171
https://zhuanlan.zhihu.com/p/609629545
源碼
## io
http://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter01/01.2.html

https://blog.kennycoder.io/2020/02/08/Golang-%E8%AA%8D%E8%AD%98-io-package%E7%9A%84%E5%8E%9F%E7%90%86%E8%88%87%E6%93%8D%E4%BD%9C/

###  NopCloser 函数
有时候我们需要传递一个 io.ReadCloser 的实例，而我们现在有一个 io.Reader 的实例，比如：strings.Reader ，这个时候 NopCloser 就派上用场了。它包装一个io.Reader，返回一个 io.ReadCloser ，而相应的 Close 方法啥也不做，只是返回 nil
![](https://i.imgur.com/TELE4hz.png)

## time
golang time
https://driverzhang.github.io/post/golang-time%E5%8C%85%E7%9A%84%E6%9C%AC%E5%9C%B0%E5%8C%96%E6%97%B6%E5%8C%BA%E4%B8%80%E6%AC%A1%E9%9C%80%E6%B1%82%E5%AE%9E%E7%8E%B0/

### formate
用fmt可以轉換是因為跑string function
但其實今天time.Duration 輸入15m ...等 會自動幫你轉換

## database/sql
### 預處理
https://www.liwenzhou.com/posts/Go/mysql/#autoid-1-3-0
處理同樣sql語 但佔位符不同value的情況
## string

1. 比較字串
可用== 或是` strings.Compare(a, b)`
strings.Compare比 == 效率更好
結果是: 0 假如 a == b,
結果為 -1 假如 a < b
結果為 1 假如 a > b.
https://play.golang.org/p/ia615JYprw
2. 檢查是否包含
`strings.Contains()`
回傳true或false
https://play.golang.org/p/lj78RhdBYq
也可用`strings.ContainsAny("failure", "ura & i")`
如果用&在contains() 還是會傳回false
https://play.golang.org/p/oeGdbA9juD
3. 轉為Unicode後比較是否包含
`strings.ContainsRune()`
https://play.golang.org/p/0puOGCxAdR
4. 計算字串中特定字之重複次數
`strings.Count()`
https://play.golang.org/p/aoJnR5C5ux
5. 忽略大小寫比較
`strings.EqualFold()`
https://play.golang.org/p/b1VgY3EazY
6. 字串轉Array
`strings.Fields("  foo bar  baz solid  ")`
以空格分隔轉為Array
https://play.golang.org/p/bGsqjtSwMN
7. 替換特殊字元後比較
(可以用strings.field就好 可以按照空白去拆)
![](https://i.imgur.com/APXZWVd.png)
要指定可以用strings.split


FieldsFunc第二個參數必須要是function 並return boolean
  ```
  f := func(c rune) bool {
        return !unicode.IsLetter(c) && !unicode.IsNumber(c)
    }
    fmt.Printf("Fields are: %q", strings.FieldsFunc("  foo1; b@ar2,baz3...", f))
```
第二個參數例如`strings.FieldsFunc("test", func (c rune) bool { return true })`
8. 測試開頭是否包含字串
`strings.HasPrefix("Gopher", "Go")`
https://play.golang.org/p/oyvjtOykj_
9. 測試結尾是否包含
`fmt.Println(strings.HasSuffix("banana", "na"))`
https://play.golang.org/p/a_lfSRdz81
10. 查看字元在字串中的位置
`fmt.Println(strings.Index("paper", "e"))`
https://play.golang.org/p/haX84zOA-1

## uft8
![](https://i.imgur.com/266ljQF.png)


## fmt
https://www.cnblogs.com/rickiyang/p/11074171.html
https://ithelp.ithome.com.tw/articles/10235988


![](https://i.imgur.com/AQZK0JK.png)
![](https://i.imgur.com/foSwkVk.png)

### print
//printf的全部教學
https://www.youtube.com/watch?v=GQ880MlHBBE&list=PLzMcBGfZo4-mtY_SE3HuzQJzuj4VlUG0q&index=5
Printf
格式化輸出，用法跟C語言的printf一樣

```
a := 10
fmt.Printf("a: %d\n", a)
```
常用到的格式化輸出輸入參數

```
%d: digit   (10進位的數字)
%c: char    (字元)
%s: string  (字串)
%v: value   (值)
%+v 見下方
%#v 見下方

%T 查看type
```
小tips
`orderNo := fmt.Sprintf("FC%02d%02d%d", now.Year()%100, int(now.Month()), int(createFunctionLog.ID))`
他還能幫你留尾巴跟限字數量

參數 v 三者的差異：
https://play.golang.org/p/UKM5CGI-AsR

```
type Name struct {
	A string
	B bool
	C int
}
func main()  {
	fmt.Printf("%v	\n", Name{})
	fmt.Printf("%+v	\n", Name{})
	fmt.Printf("%#v	\n", Name{})
}
// { false 0}	
// {A: B:false C:0}	
// main.Name{A:"", B:false, C:0}	
```

**【fmt.Print】
【fmt.Println】**
兩者與fmt.Printf相比，差在不能印格式化輸出
Print與Println兩者主要差在ln多了一個換行(new line)

https://www.youtube.com/watch?v=SoMMz770X34&list=PLujhHB_uAFJws6Vv5q1KDoaQ4YcpS9UOm&index=10
![](https://i.imgur.com/Dm1qM1M.png)
比較特別在+v 如果是struct可以有欄位名稱
+d出來一定正數


**跳脫字元**
" "雙引號 內可跳脫字元\t \n等  

` `重音符 內則保留原始字串 


### sprint
**【fmt.Sprint】
【fmt.Sprintln】
【fmt.Sprintf】**
fmt.Sprint 不會印出東西，基本上是拿來組合字串用的
組出來之後，需要一個變數去接
用fmt.Sprint組字串，比起操作字元、陣列，可讀性會較高一些。

```
func main()  {
	s1 := "I"
	s2 := "am"
	s3 := "string"

	str1 := fmt.Sprintln(s1, s2, s3)
	fmt.Println(str1)

	str2 := fmt.Sprint(s1, s2, s3)
	fmt.Println(str2)
}
/* result:
I am string

Iamstring

*/
```

### Eprint
寫入 可對io用 ex http的response

## bufio
![](https://i.imgur.com/fmIvtUQ.png)

bufio VS ioutil 库： bufio 和 ioutil 库都提供了读写文件的能力。它们之间唯一的区别是 bufio 有一个额外的缓存层。这个优势主要体现在读取大文件的时候。


NewScanner
建立一個新的掃描器物件
![](https://i.imgur.com/U3regs7.png)
建立完成放入可以掃描
Scan

![](https://i.imgur.com/cpAxvXw.png)

scanner.newScanner是預設split用空白 你可以看他new放入的split func
如果要不同的切割方式只要實現splitfunc就好 有三四個可以用
自訂也可以

## io
http://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter01/01.1.html


![](https://i.imgur.com/Z321Dum.png)

![](https://i.imgur.com/rC3ofNX.png)
https://www.youtube.com/watch?v=lNAXk7YFPhM&ab_channel=FangChannel


![](https://i.imgur.com/KTtI6C4.png)


1. io.Reader/Writer 常用的几种实现
1. net.Conn: 标识网络连接。
1. os.Stdin, os.Stdout, os.Stderr: 标准输入、输出和错误。
1. os.File: 网络,标准输入输出,文件的流读取。
1. strings.Reader: 字符串抽象成 io.Reader 的实现。
1. bytes.Reader: []byte抽象成 io.Reader 的实现。
1. bytes.Buffer: []byte抽象成 io.Reader 和 io.Writer 的实现。
1. bufio.Reader/Writer: 带缓冲的流读取和写入（比如按行读写）。
1. 除了这几种实现外常用的还有ioutil工具库包含了很多IO工具函数，编码相关的内置库encoding/base64、encoding/binary等也是通过 io.Reader 和 io.Writer 实现各自的编码功能的。

这些常用实现和工具库与io.Reader和io.Writer间的关系可以用下图表示。

![](https://i.imgur.com/QflUGC2.png)

### Seeker 
![](https://i.imgur.com/alkvYGQ.png)
![](https://i.imgur.com/CJavK6R.png)
### SectionReader 
![](https://i.imgur.com/oIelgro.png)

### PipeReader 和 PipeWriter 类型
![](https://i.imgur.com/TuiOt3i.png)
![](https://i.imgur.com/XwVr6LQ.png)
### Copy 和 CopyN 函数
![](https://i.imgur.com/NklMJTj.png)



## os
os.Stdin抓取標準輸入
Stat讀取文件

os.args可以抓命令行參數(第一參數為當前執行文件位置)

![](https://i.imgur.com/j8tLPqZ.png)

![](https://i.imgur.com/DHTcKjQ.png)
![](https://i.imgur.com/KZC7GuK.png)

## bufio
![](https://i.imgur.com/aYo4Fov.png)

## flag
![](https://i.imgur.com/iB1bSNl.png)

## ioutil
![](https://i.imgur.com/Mt8AMvk.png)
### NopCloser 
![](https://i.imgur.com/lOubAbT.png)
### ReadDir 函数
![](https://i.imgur.com/dLaUByM.png)
![](https://i.imgur.com/JEvjn2S.png)
### TempDir 和 TempFile 函数
![](https://i.imgur.com/5Y3aY9K.png)

### tempfile
如果要讀取記得要改Seek 
https://stackoverflow.com/questions/64146997/reading-data-just-written-to-a-temp-file
## mime/multipart 

##  pprof
可以查看效能問題
https://www.liwenzhou.com/posts/Go/pprof/
## log
https://github.com/jincheng9/go-tutorial/tree/main/workspace/std/01
![](https://i.imgur.com/lQyhI40.png)
![](https://i.imgur.com/MvCBXbx.png)
![](https://i.imgur.com/4dNZrRZ.png)



## strconv
![](https://i.imgur.com/9tZzWin.png)

str轉換率
可以用
strconv.ParseInt()去轉化
後面第一個是進位
第二是大小 返回结果的bit大小 也就是int8 int16 int32 int64
![](https://i.imgur.com/Was85CP.png)


## time
https://www.youtube.com/watch?v=uUBwIx0VNMw&ab_channel=FangChannel
https://www.youtube.com/watch?v=Rs9-0m3DsBE

注意雷

time.Time這種struct 他在跑json或fmt這種 他會去檢查type是struct的有沒有inplment對應的function

string() method
如果有就把他轉變成string
https://go.dev/play/

至於原理看這兩篇
https://stackoverflow.com/questions/46147641/why-is-time-in-go-printed-differently-in-a-struct


https://stackoverflow.com/questions/33119748/convert-time-time-to-string    

### timer
a := time.NewTimer(d) 計時器 d是幾秒
<-a.c
one buffer 所以要取出來

reset 要先把裡面的.c 取出來 不然空間只有一 會有問題
## ticker
打點器 可以一直多久做一次
![](https://i.imgur.com/MlgyJcP.png)

## rand

rand.Seed(time.Now().UnixNano())

这是初始化种子。

不然每次产生的随机数都一样，默认是rand(1)

## pprof 找效能曼的原因
https://www.youtube.com/watch?v=4A7q99ggyKc&list=PLKhlVcCW5bA2WGUs4Y7cRhQ8SSBAGVOTR&index=26
## atomic

![](https://hackmd.io/_uploads/By2kuefn2.png)

![](https://i.imgur.com/fLMaUbp.png)
![](https://i.imgur.com/FOtEkBx.png)

https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson26


除了數字加減以外 可以改變struct之類的也可以 用value方法
原子性操作都可以

![](https://i.imgur.com/iAgBNhj.png)
上面跟下面一樣的
但上面效能比下面好
https://www.youtube.com/watch?v=xXi9yWbXkHU&ab_channel=GolangDojo
```

func AtomicTest() {
	var diffSum int64
	fmt.Println(atomic.LoadInt64(&diffSum))
	atomic.StoreInt64(&diffSum, 5)
	fmt.Println(diffSum)


    //下面教你操作不是int之類的 操做struct
	var v atomic.Value
	daniel := ninja{ name: "Daniel" }
	v.Store(daniel)	
	var wg sync.WaitGroup
	wg.Add(1)

	go func ()  {
		danielNinja := v.Load().(ninja)
		danielNinja.name = "not ninja"
        //這邊不是傳&
		v.Store(danielNinja)
		wg.Done()
	}()
	
	wg.Wait()

	fmt.Println(v.Load())
}

type ninja struct {
	name string
}
```

## runtime
![](https://i.imgur.com/97f8fb1.png)


## csv

### writer
https://myapollo.com.tw/zh-tw/golang-csv-writer/
![](https://i.imgur.com/ICl51WL.png)

### reader

必看readAt vs read
https://juejin.cn/post/6900534635181113352

https://myapollo.com.tw/zh-tw/golang-csv-reader/
![](https://i.imgur.com/rfw5UTP.png)
 ReadAll 函式，差別在於 ReadAll 會一次讀完整個 CSV 資料，會同時回傳 [][]string 與 error 結果，在 CSV 資料量很大的時候， ReadAll 很可能會一次消耗掉大量記憶體，必須注意。另外是， ReadAll 並不會將 io.EOF 視為 error 回傳。
## sync

https://www.cnblogs.com/rickiyang/p/11074167.html

https://zhuanlan.zhihu.com/p/412666957
sync and atomic

add幾個 就要done幾次
![](https://i.imgur.com/O4jcKrN.png)

多個go 執行同一個任務


當一個完成其他就停止


### 信號 semaphore
最大多少
https://zhuanlan.zhihu.com/p/389718532

### atomic
https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson26
![](https://i.imgur.com/x7G9v6m.png)

value可以用在config文件配置之類的
如果有靈界區之類的就用lock 
不然newConfig LoadConfig可以用看看value


### Sync.WaitGroup, why closer in a goroutine
https://stackoverflow.com/questions/34818798/sync-waitgroup-why-closer-in-a-goroutine

### waitGroup
https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson21
![](https://i.imgur.com/qHeFHv5.png)
![](https://i.imgur.com/X4SAPlA.png)

### sync.once
https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson22

![](https://i.imgur.com/xR4tNez.png)


https://learnku.com/articles/51115
https://www.youtube.com/watch?v=9yyAI3tD97Q&ab_channel=GolangDojo

### sync.Pool 
https://www.youtube.com/watch?v=PnYItFJy7IQ&ab_channel=GolangDojo
https://www.cnblogs.com/qcrao-2018/p/12736031.html


https://cyent.github.io/golang/goroutine/sync_pool/
記住要夠大再用pool不要太小用 這樣反而更浪費


。常用于一些对象实例创建昂贵的场景。注意，Pool 是 Goroutine 并发安全的。

sync.Pool 本质用途是增加临时对象的重用率，减少 GC 负担。划重点：临时对象。所以说，像 socket 这种带状态的，长期有效的资源是不适合 Pool 的。
而且他無序

当用完一个从 Pool 取出的实例时候，一定要记得调用 Put，否则 Pool 无法复用这个实例，通常这个用 defer 完成；
### sync.cond(條件鎖)
Cond是sync包里的一个结构体类型，表示条件变量。我们知道sync.WaitGroup可以用于等待所有goroutine都执行完成，sync.Cond可以用于控制goroutine什么时候开始执行


https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson24

https://www.youtube.com/watch?v=NIvSQCwcots&ab_channel=GolangDojo

然後可以用
Signal & Broadcast去發送信號
signal 只能一個
broadcast可以多個
### LoadOrStore
https://xnum.github.io/2018/11/syncmap-loadorstore/
### Map

https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson25

https://www.youtube.com/watch?v=X8tRAW8P7-U&ab_channel=GolangDojo
![](https://i.imgur.com/JAwxGth.png)
比較麻煩是range 不能直接用 要呼叫function
![](https://i.imgur.com/Ng0LjsF.png)

loadAndDelete是有atomic的操作
![](https://i.imgur.com/TVnxfrZ.png)



## time
https://blogtitle.github.io/go-advanced-concurrency-patterns-part-2-timers/
time一些問題

## context
https://github.com/jincheng9/go-tutorial/blob/main/workspace/senior/p28/08-go-context-management.md

https://blog.wu-boy.com/2020/05/understant-golang-context-in-10-minutes/

https://www.youtube.com/watch?v=h2RdcrMLQAo&ab_channel=TutorialEdge


https://www.youtube.com/watch?v=uwyG6msSOSY 蠻不錯的 
跟waitGroup不一樣

兩種控制併發的方式

backgroupd就是new emty context

### dealine
可以控制多久關閉    
可以主動or時間到自己會cancel

### timeout
WithTimeout是執行的便捷函數WithDeadline(parent, time.Now().Add(timeout))


### withValue
共享 key value
雖然ValueContent本來就能存了
但還是用這個會比較好理解    

### RWNutex vs Mutex

Mutex是sync包里的一个结构体类型，含义就是互斥锁。Mutex变量的默认值或者说零值是一个没有加锁的mutex，也就是当前mutex的状态是unlocked。


Go的锁是不可重入的，没有递归锁
* 允许一个goroutine加锁，另一个goroutine解锁，不要求加锁和解锁在同一个goroutine里
* sync.Mutex的零值是没有加锁的Mutex，sync.RWMutex的零值是没有加锁的RWMutex
* 更多细节可以参考References里Mutex和RWMutex的官方说明


![](https://i.imgur.com/N0qSYnO.png)
https://github.com/jincheng9/go-tutorial/tree/main/workspace/lesson23


讀寫鎖在密集操作比較好

因為可以多人同時有讀鎖

讀者不必互相等待。他們只需要等待持有鎖的寫入者

遇到 race condition 的時候可以考慮用 sync.Mutex 來解決，有讀寫阻塞的時候可以用 sync.RWMutex
syncRWMutex 可以有同時允許多個 RLock 和 RUnlock 但只能有一個 Lock 和 Unlock


## sort
![](https://i.imgur.com/IrdcIAK.png)
### 自訂

多欄位排序
https://loesspie.com/2018/05/07/go-sort-with-multiple-parameters/

排序
![](https://i.imgur.com/hKPa183.png)
查找
![](https://i.imgur.com/TQdA0Id.png)
### interface
https://www.youtube.com/watch?v=3ZbzGwmtwAg&list=PLBjZhzRvV2ChPTPNDx_apHdKa9Ha7LVpN&index=49
![](https://i.imgur.com/67iMys9.png)
    
## Traefik
https://www.youtube.com/watch?v=0GkJb6-CDUU&list=PLKhlVcCW5bA2WGUs4Y7cRhQ8SSBAGVOTR&index=43

## godotenv


## golang ci (只能用在github)
可以幫你跑ci 看一些問題
opensorce免費 

## go-critic
不要太大的專案可以用
因為太大他會掃全部程式碼

他會看你的用法 那裡用不好 非常建議用

## redis
![](https://i.imgur.com/lheYkeQ.png)
![](https://i.imgur.com/78vklay.png)

cmd可以指定類型 因為他retrun interface
所以可以先轉類型
他還可以轉成類型sline
![](https://i.imgur.com/hAdAedg.png)


## json
https://www.liwenzhou.com/posts/Go/json-tricks/

https://stackoverflow.com/questions/25087960/json-unmarshal-time-that-isnt-in-rfc-3339-format

    
```
type Ninja struct {
	Name   string `json:"full_name"`
	Weapon Weapon `json:"weapon"`
	Leavel int `json:"leavel"`
}

type Weapon struct {
	Name string `json:"weapon_name"`
	Leavel int `json:"weapon_leavel"`
}
```
![](https://i.imgur.com/KtKFvsR.png)
解析json 跟 go object to json


https://www.youtube.com/watch?v=x7gkIvAI2-w tag

![](https://i.imgur.com/rZ6CqHm.png)

### json tag轉換
![](https://i.imgur.com/abvfsuY.png)

### map
https://juejin.cn/post/7029572806517981214

### 解構JSON
https://blogtitle.github.io/unmarshaling-json-in-golang/
![](https://i.imgur.com/q4DVZjP.png)
最好用indent的 不會亂

### 放入map
如果 JSON 数据的定义过于复杂，我们需要一种更加灵活的方式来处理。在这种情况下，可以将 JSON 数据映射到一个 map 结构中。
https://www.cnblogs.com/liuhe688/p/10971332.html
### tag
- 不會傳 igonor
- omitempty 空就不傳 (記住 int 0 , bool false會被用掉)

nil 會轉null


### validated
https://www.youtube.com/watch?v=nvs7YPp2-Ok
會幫你驗證是不是json格式

### 不確定資料格式
![](https://i.imgur.com/KIHOwyU.png)
不確定資料格式用json接 然後型態斷言
![](https://i.imgur.com/zDUtTzQ.png)
資料格式對應

https://www.youtube.com/watch?v=nvs7YPp2-Ok&list=PLIud7iV0oWk-oQ6Da7WyrGShZ-auYZq8e&index=19&ab_channel=%E8%82%AF%E5%B0%BC%E6%94%BB%E5%9F%8E%E7%8D%85
這邊有說怎做

### deconder and encoder
一樣解析json但是 是對應stream的
os輸入輸出 或 讀檔案

https://www.cnblogs.com/liuhe688/p/11105571.html

### 時間解析
https://www.youtube.com/watch?v=e4BBUjAsr8M
用覆寫 不太懂
我比較喜歡自訂型態
https://www.youtube.com/watch?v=-GO9xHok3JA

### customer type
https://www.youtube.com/watch?v=UmVYkEYm4hw


## raw message
https://juejin.cn/post/7149848236017057805
https://learnku.com/articles/76365

## temple
https://www.jianshu.com/p/88bbf78ab043
https://opensourcedoc.com/golang-web-programming/template-language/
![](https://i.imgur.com/dJdjBb6.png)


temple
```
{{ .Secret }}
{{ .Name }}
```

把object to temple
如果是html要import html不是txt的

### Execute vs ExecuteTemplate
https://colobu.com/2016/10/09/Go-embedded-template-best-practices/
## safeHTML
更好 可以防XSS
https://blogtitle.github.io/go-safe-html/

## html

可以自己定義serve config
![](https://i.imgur.com/Dzf9mL9.png)


### method
https://learnku.com/articles/23430/golang-learning-notes-1-http-client-foundation

get 的query string 只能用fmt.Printf去加入

postForm一定是用post method加上form
https://stackoverflow.com/questions/30652577/go-doing-a-get-request-and-building-the-querystring

## http

https://juejin.cn/post/7284464014447640630
![](https://i.imgur.com/2yVHVCS.png)

https://www.jianshu.com/p/be3d9cdc680b 解析
https://willh.gitbook.io/build-web-application-with-golang-zhtw/03.0/03.4
前面是註冊
lisen那邊會抓出對應的mux的handler type
然後跑那個handler func的serverHttp




![](https://i.imgur.com/QQ90jzo.jpg)
![](https://i.imgur.com/AqxSioe.png)

### router


#### 參數
![](https://i.imgur.com/eaMpF2s.png)
![](https://i.imgur.com/KXzYH9r.png)



### assets
https://myapollo.com.tw/zh-tw/golang-http-fileserver/
最好不要用DIR 因為可以存取 權限太大
#### http dir
https://segmentfault.com/q/1010000012403920

### flush
Flusher 接口由 ResponseWriters 實現，它允許 HTTP 處理程序將緩衝數據刷新到客戶端。

默認的 HTTP/1.x 和 HTTP/2 ResponseWriter 實現支持 Flusher，但 ResponseWriter 包裝器可能不支持。處理程序應始終在運行時測試此功能。

請注意，即使對於支持 Flush 的 ResponseWriters，如果客戶端通過 HTTP 代理連接，則緩衝的數據可能在響應完成之前無法到達客戶端。
https://stackoverflow.com/questions/19292113/not-buffered-http-responsewritter-in-golang


## heap
https://juejin.cn/post/7152136155410989092

## embed
處理靜態文件被編譯後找不到問題
https://learnku.com/courses/go-video/2022/007-use-embed-to-package-templates-and-static-files/11574
###### tags: `Go`