## ![](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`