Go 語言系列(十二):常見陷阱與反模式
這是 Go 語言從零到 Web 應用系列的第十二篇,也是本系列的最終篇。這篇整理 Go 開發中最常踩到的陷阱——即使是有經驗的 Go 開發者也可能中招。每個陷阱都附帶「踩坑範例」和「正確做法」,讓你一次看清問題在哪。 Slice 陷阱 陷阱 1:Append 可能修改原始 Slice 當 slice 的 capacity 還有剩餘空間時,append 會直接修改底層 array,影響到共享同一個 array 的其他 slice。 package main import "fmt" func main() { original := make([]int, 3, 5) // len=3, cap=5 original[0], original[1], original[2] = 1, 2, 3 // 截取一個子 slice sub := original[:2] // append 到 sub — cap 還有空間,不會分配新 array sub = append(sub, 99) fmt.Println("original:", original) // [1 2 99] ← 被改了! fmt.Println("sub:", sub) // [1 2 99] } 正確做法: 使用 full slice expression 限制 capacity // 用 original[:2:2] 限制 sub 的 cap = 2 sub := original[:2:2] // 現在 append 會分配新 array,不影響 original sub = append(sub, 99) fmt.Println("original:", original) // [1 2 3] ← 沒被改 fmt.Println("sub:", sub) // [1 2 99] 陷阱 2:大 Slice 截取小片段導致記憶體無法釋放 // 錯誤:小 slice 持有大 array 的引用,GC 無法回收 func getFirstTen(data []byte) []byte { return data[:10] // 底層 array 整個被保留 } // 正確:複製需要的資料到新 slice func getFirstTen(data []byte) []byte { result := make([]byte, 10) copy(result, data[:10]) return result // 原始的大 array 可以被 GC 回收 } 假設 data 是 1GB 的檔案內容,用截取的方式只取 10 bytes,那 1GB 的底層 array 都不會被回收。 ...