Go MOC
用途:這張地圖串連了關於「Go 語言」的相關筆記,作為導航層。 上層:Software Engineering MOC
變數與型別
- Go 宣告變數的四種寫法 —
var為基礎、型別後置,函式內可用:= - Go 的基本型別與預設推斷型別 — 位寬寫進名字裡;推斷一律給
int/float64/complex128 - Go 不允許宣告了卻沒用到的變數 — 沒用到是編譯錯誤,所以
_到處都是 - Go 的可見性由開頭字母大小寫決定 — 大寫 exported、小寫只在 package 內;連 struct 欄位與 json 都受影響
函式
- Go 函式的多回傳值與具名回傳值 — 參數簡寫、多回傳值、naked return 的可讀性代價
- Go 的函式是一等公民,閉包捕捉的是變數本身 — 當值傳遞;閉包捕捉變數不是值
- defer 是後進先出,登記時機在執行到那一行 — 作用域是函式不是區塊,迴圈裡會堆到最後
控制流程
- Go 只有 for 一種迴圈 — 沒有 while,拿掉三段式的前後兩段就是
- Go 的 if 可以先宣告變數且作用域涵蓋 else — 判斷式前可放初始化陳述句
- Go 的 switch 預設不 fallthrough — 不用寫 break,且可省略判斷式當 if-else-if 用
- Go 沒有 truthy falsy,判斷式只吃 bool — 非 bool 放進判斷式是編譯錯誤;
if err != nil的由來
集合型別:Array 與 Slice
- Slice 是看向底層 array 的一扇窗戶 — header 三欄位:len 看得到多少、cap 最多能往右拉多寬
- Slice 的四種建立方式與 nil — make 的三種給法;nil slice 沒有底層 array 但能直接 append
- Go 的切割上限是 cap 而不是 len —
x[a:b]的 b 可超過 len;從 array 切出來 cap 吃到底 - append 的行為取決於 cap 夠不夠 — 就地寫入 vs relocate;擴容 = 配置 + 整份複製
- 切割出的 slice 預設 cap 吃到底,append 會寫進鄰居的地盤 — dir1/dir2 陷阱與 full slice expression
- Go 傳 slice 是複製 header 而不是 pass by reference — 複製窗戶的框,房子還是同一間
- copy 是唯一真的複製 slice 資料的方式 — 其餘操作都只複製 header
- Go 移除 slice 特定 index 的元素會打亂順序 — 交換法 O(1) 但順序變,保序要付 O(n)
- Go 的 slice、map、func 不能用相等運算子比較 — 只能跟 nil 比,要比內容用 slices.Equal
- Go 的 slice 擴容倍率在大 slice 時還是 2 倍嗎 — ❓待驗證
Struct
- Go 的 struct 是一組具名欄位的集合 — 值型別、整份複製;指標也用
.取值
Map
- Go 建立 map 的三種寫法 — var / make / 字面量,只有第一種不能寫
- nil map 可以讀但不能寫 — 寫入 panic;與 nil slice 可直接 append 的不對稱
- Go 的 map 讀取不存在的 key 會回傳 zero value — 前面是值後面是 bool;comma ok 是語言內建語法
- make 只用於 map、slice、channel — 只有這三種需要 runtime 先初始化內部結構
集合走訪
- Go 的 range 回傳 index 與 value — 只接一個變數拿到的是 index
- Go 1.22 起迴圈變數每次疊代各自一份 — 舊教學的
&v陷阱已失效;語意看 go.mod
指標
- Go 的 & 取址與 * 解參考 — 打包成位址 vs 拆開看裡面
並行(Concurrency)
- Goroutine 是用 go 關鍵字啟動的輕量任務 — runtime 排程、main 結束就全被砍
- Channel 是 goroutine 之間的通訊管道 — 用傳訊息取代共享記憶體
- 無緩衝 channel 的收送會互相等待 — channel 同時也是同步點
- 用 time.Sleep 等 goroutine 只是 demo 寫法 — 正解是等事件(channel / WaitGroup)不是等時間
select
- select 是 channel 版的 switch — 同時盯多根管子,誰先就緒誰贏;多個就緒時隨機挑
- select 的 case 後面不是條件而是一個 channel —
time.After是管子不是條件判斷 - select 分三階段:求值全部、等待全部、只執行一個 — 求值有副作用,沒被選中的照樣發生
- select 阻塞的是呼叫它的 goroutine,不是整個程式 — 一條執行流收割多條平行工作
- select 等不到條件時會 deadlock 或 goroutine leak — panic 是幫你,沉默的 leak 才可怕
- select 用 default 做非阻塞,用 time.After 做逾時 — 兩者互斥,不要同時寫
- for-select 裡的 time.After 每圈重置 — 寫在迴圈裡是 idle timeout,總時限要拉到外面
- 把 channel 設成 nil 可以停用 select 的某個 case — nil channel 永遠 block 的正面用法