📌 30 秒摘要(讀完用自己的話寫一句)

這篇在講:JetBrains 出的 agent plugin,塞給 coding agent 一份「現代 Go 寫法對照表」,讓它別再產出過時的 Go。真正值得記的是它的動機分析——它指名了 coding agent 產出過時程式碼的兩個不同原因,其中第二個(頻率偏誤)是所有語言、所有 agent 共通的問題,跟 Go 無關。

🎯 為什麼存這篇 / 未來想拿它做什麼

  • 「模型知道某個 API ≠ 它會用」這個洞察,我可以套到任何快速演進的技術棧上。
  • 高影響那幾條(slices.Containsfor i := range nerrors.Iscmp.Or)是 code review 時人眼該認得的——就算不裝 plugin,知道這幾條也有用。
  • 這是我知識庫裡第一份 Go 相關筆記

🧰 這篇給我的工具(連到 tools/ 工具卡)

✨ 關鍵重點

1. ⭐ 它指名了兩個不同的失敗原因——而且解法不同

Training data lag. Models don’t know about features added after their training cutoff.
Frequency bias. Even for features the model knows, it often picks older patterns. There’s more for i := 0; i < n; i++ in the training data than for i := range n, so that’s what comes out.

我的補註:第二個才是真正麻煩的。訓練資料落後可以靠「餵它新文件」解決;但頻率偏誤不會因為模型知道新寫法就消失——它的輸出跟隨訓練語料的分布,不是新穎度或品質。所以光說「請用最新的寫法」沒用,要給它明確的對照表

2. 它會先偵測專案的 Go 版本

go.mod 讀出版本,只用到該版本為止可用的特性。這點很重要——否則就是把編不過的程式碼塞給你。

3. 涵蓋 Go 1.0 → 1.27,對齊官方 modernize analyzer

定位講得很清楚:官方的 modernize analyzer 是把既有程式碼自動更新成新慣用法;這份 guidelines 是讓 agent 一開始就寫對,減少之後要修的量。

4. 高影響條目速查(Critical/High,共 38 條中的一部分)

Critical(幾乎每個專案都有、數十處)

診斷Go舊寫法 → 新寫法
slicescontains1.21手寫搜尋迴圈 → slices.Contains(s, needle)
rangeint1.22for i := 0; i < n; i++for i := range n
efaceany1.18interface{}any
erris1.13err == os.ErrNotExisterrors.Is(err, os.ErrNotExist)
err.(*os.PathError)errors.As(err, &e)

High(常見、每專案 5–20 處)

診斷Go舊寫法 → 新寫法
cmpor1.22一串 if x == "" { x = ... }cmp.Or(a, b, "default")
minmax1.21if a < b {...} else {...}min(a, b) / max(a, b)
sortslice1.21sort.Sliceslices.SortFunccmp.Compare
forvar1.22迴圈裡的 v := v不再需要(1.22 改了迴圈變數語義)
errorsjoin1.20fmt.Errorf("multiple: %v", errs)errors.Join(errs...)(可被 errors.Is/As 穿透)
stringsseq1.24range strings.Split(...)range strings.SplitSeq(...)(省掉中間 slice 配置)
stringscutprefix1.20HasPrefixTrimPrefixstrings.CutPrefix
waitgroup1.25wg.Add(1)go func(){ defer wg.Done() ... }wg.Go(func(){...})
testingcontext1.24context.WithCancelt.Context()
mapkeysvalues1.23手動蒐集 → maps.Keys / maps.Values
timesince1.0time.Now().Sub(t)time.Since(t)
newliteral1.26x := 42; p := &xp := new(42)(任何型別都適用)

其餘 Medium/Low 條目涵蓋 clear()maps.Cloneslices.Reversecontext.WithCancelCausesync.OnceValueatomic.Pointer[T]fmt.Appendfb.Loop()omitzerohttp.ServeMux 新路由語法等。

注意FEATURES.md 開頭自標 “Work in progress — inconsistencies may be present.”

5. 一個值得學的安全設計

README 明說:scripts/dev-install.sh 刻意與 agent 面對的 wrapper 分開,好讓 agent 永遠無法觸發建置
我的補註:這跟 工具-防止agent造假通過驗收 的第 5 點是同一個心法——能造成危害的路徑,就從結構上讓 agent 碰不到,而不是靠指令叫它別做。

💬 原文摘錄

  • 兩個失敗原因(本篇最值得記的一段):

    “Training data lag. Models don’t know about features added after their training cutoff. They can’t use errors.AsType[T] (Go 1.26) if they’ve never seen it.”
    “Frequency bias. Even for features the model knows, it often picks older patterns. There’s more for i := 0; i < n; i++ in the training data than for i := range n, so that’s what comes out.”

  • 與官方工具的分工:

    “The modernize analyzer exists to automatically update existing code to use newer idioms. These guidelines serve the same goal for new code: agents write modern Go from the start, so there’s less to fix later.”

  • 安全邊界:

    scripts/dev-install.sh, which is intentionally separate from the agent-facing wrapper so an agent can never trigger a build.”

🔗 相關

  • Effective Go搭配看:那篇講「Go 為什麼長這樣」(心智模型,變得慢),這篇講「現在該怎麼寫」(語法與 API,變得快)。那篇的 Errors 章教的 type switch 辨識錯誤,正是這裡標為 Critical 的 erris 要換掉的寫法
  • 收藏頁的卡 — 四個平台的安裝指令速查