Upgrade to Pro — share decks privately, control downloads, hide ads and more …

go fix - Go 1.27 の modernizer 事情

go fix - Go 1.27 の modernizer 事情

LOGOSWARE.go#1 - Go 1.27 Release Party での登壇資料です。

Avatar for kudohiroki

kudohiroki

August 25, 2026

Other Decks in Programming

Transcript

  1. go fix Go 1.27 の modernizer 事情 工藤 弘樹 /

    2026-08-25 LOGOSWARE.go#1 - Go 1.27 Release Party
  2. LOGOSWARE.go#1 - Go 1.27 Release Party あなたのGo、いつ製? for i :=

    0; i < len(items); i++ { ... } if a < b { x = a } else { x = b } どちらも2026年の書き方ではない © 2026 LOGOSWARE Corporation | 2
  3. LOGOSWARE.go#1 - Go 1.27 Release Party だいたいAIが書くコード、古い書き方だらけ 「最新の Go 1.25

    のイディオムで書いて」と指示しても、出てこない ときには 「そんな機能は存在しない」と否定してくる チームが同じ壁にぶつかったのは 2024年12月 coding assistants は既存のGoの大半で訓練されているので 古いイディオムを出し続ける Go — go.dev/blog/gofix © 2026 LOGOSWARE Corporation | 3
  4. LOGOSWARE.go#1 - Go 1.27 Release Party 武器として選ばれた go fix 年生まれ。

    Go 1 より前の破壊的変更に追従するための道具 Go 1 の互換性保証が始まり、役目を失う 以後 10年以上、化石( os.Error を直してくれた。今もう無いけど) 隣の go vet だけがどんどん進化していった 2011 © 2026 LOGOSWARE Corporation | 5
  5. LOGOSWARE.go#1 - Go 1.27 Release Party Go 1.26 で完全に書き換え go

    fix has been completely revamped and is now the home of Go's modernizers — Go 1.26 Release Notes 昔の fixer は 全部消えた(もう出番のないものばかり) 代わりに入ったのが modernizer = 今のイディオムに書き換える analyzer 土台の analysis framework は go vet と完全に同じ。実装もほぼ同じ 本質的な違いは入場条件 — fix には何も悪化させない修正しか置かれない © 2026 LOGOSWARE Corporation | 6
  6. LOGOSWARE.go#1 - Go 1.27 Release Party 使い方:1コマンド $ go fix

    -diff ./... $ go fix ./... プレビュー(直すところがあれば exit 1) # 適用。成功すると、何も言わずに書き換わる # と同じ package パターン 成功時は静かにソースが書き換わる go build / go vet © 2026 LOGOSWARE Corporation | 7
  7. LOGOSWARE.go#1 - Go 1.27 Release Party Go 1.26 実測:ループ編 func

    Sum(n int) int { total := 0 for i := 0; i < n; i++ { + for i := range n { total += i } func Clamp(a, b int) int { if a < b { x = a } else { x = b } + x = min(a, b) 値の for を range n に minmax (go1.21) — 大小比較の if/else を組み込みの min / max に rangeint (go1.22) — 3 © 2026 LOGOSWARE Corporation | 8
  8. LOGOSWARE.go#1 - Go 1.27 Release Party Go 1.26 実測:文字列編 +

    + if i := strings.IndexByte(pair, '='); i >= 0 { return pair[:i], pair[i+1:] if before, after, ok := strings.Cut(pair, "="); ok { return before, after } + for _, line := range strings.Split(text, "\n") { line := line for line := range strings.SplitSeq(text, "\n") { + + s := "" s += p + "," var s strings.Builder s.WriteString(p + ",") +スライスを strings.Cut に stringsseq / forvar — Split を SplitSeq に(スライスを作らない) 。 1.22 で不要になった line := line も同時に消える stringsbuilder — ループ内の += を strings.Builder に stringscut — Index © 2026 LOGOSWARE Corporation | 9
  9. LOGOSWARE.go#1 - Go 1.27 Release Party Go 1.26 + +

    + 実測:並行処理編 for _, job := range jobs { wg.Add(1) go func() { defer wg.Done() job() }() wg.Go(func() { job() }) } / go / Done の3点セットを wg.Go 1本に Go 1.27 で waitgroupgo に改名 waitgroup (go1.25) — Add © 2026 LOGOSWARE Corporation | 10
  10. LOGOSWARE.go#1 - Go 1.27 Release Party Go 1.27 の go

    fix 差分 +4 atomictypes embedlit slicesbackward unsafefuncs −1 fmtappendf … removed due to stylistic concerns 改名 waitgroup → waitgroupgo 登録 analyzer:22 → 26 (go1.26.4 と go1.27.0 の go tool fix help 実測) © 2026 LOGOSWARE Corporation | 11
  11. LOGOSWARE.go#1 - Go 1.27 Release Party embedlit — 構造体リテラルのキーの変更 の言語変更:構造体リテラルのキーに

    埋め込みフィールドのセレクタが書けるようになった Go 1.27 type Wrapped struct { Base; Extra bool } // Base は埋め込み そして同じリリースで書き換えツールが来た -return Wrapped{Base: Base{ID: 1, Name: "go"}} +return Wrapped{ID: 1, Name: "go"} embedlit — +4のうち唯一、 go.mod が go 1.27 でないと発火しない © 2026 LOGOSWARE Corporation | 12
  12. LOGOSWARE.go#1 - Go 1.27 Release Party 偶然ではない理由 は 言語・標準ライブラリの変更を承認するたび 「modernizer

    を添えるべきか」を検討している proposal review group — go.dev/blog/gofix 新機能 + 移行ツール = セットで出荷する時代 © 2026 LOGOSWARE Corporation | 13
  13. LOGOSWARE.go#1 - Go 1.27 Release Party slicesbackward — 逆順ループの1行化 狙いは読みやすさ

    — さっきの rangeint / minmax と同じ族で、消えるバグはない -for i := len(s) - 1; i >= 0; i-- { +for _, v := range slices.Backward(s) { は go1.23 の iterator。インデックスと値の両方が取れる +4 のうち 3つは既存APIへの追従(go1.17 / 1.19 / 1.23) 同じリリースの言語変更に対応したのは embedlit だけ slices.Backward © 2026 LOGOSWARE Corporation | 14
  14. LOGOSWARE.go#1 - Go 1.27 Release Party 事故を減らす新顔: atomictypes / unsafefuncs

    どちらも読みやすくするための書き換えではない — バグが構造的に消える -var counter int64 +var counter atomic.Int64 func Incr() int64 { return atomic.AddInt64(&counter, 1) + return counter.Add(1) 非アトミックアクセスが 型で禁止され、 32bit環境のアラインメント問題も消える atomictypes — -unsafe.Pointer(uintptr(ptr) + uintptr(n)) +unsafe.Add(ptr, n) unsafefuncs — uintptr は GCが追跡しない整数。対象APIは go1.17(5年前) © 2026 LOGOSWARE Corporation | 15
  15. LOGOSWARE.go#1 - Go 1.27 Release Party fmtappendf 削除の理由 w.Write([]byte(fmt.Sprintf(...))) w.Write(fmt.Appendf(nil,

    ...)) fmt.Fprintf(w, ...) の fmtappendf は こう直す。でも本当は こう書くべきだった // 1.26 // // より良い修正を機械的な修正が塞いでしまう 速さも根拠にならなかった — 実測は Appendf の方が遅い 58〜62ns → 63〜69ns、alloc 数は同じ(golang/go#73666) 挙動が変わるので最初から入っていない仲間たち appendclipped (nil性)/ slicesdelete (末尾ゼロ埋め)/ bloop (ベンチ値が変わる) © 2026 LOGOSWARE Corporation | 16
  16. LOGOSWARE.go#1 - Go 1.27 Release Party ./... 一括適用の安全性 バージョンゲート: go.mod

    の go / build tag より新しい機能は入れない 生成コードは触らない(直すべき場所は generator) 大量の修正は 3-way merge、衝突した修正は 捨てて警告 未使用 import は最後に 自動で掃除 変数が未使用になる等の semantic conflict は 人間の仕事 → ビルドが落ちるので見逃せない …ただし、1つ目には穴がある © 2026 LOGOSWARE Corporation | 17
  17. LOGOSWARE.go#1 - Go 1.27 Release Party 踏んだ罠:ファイル名の直接指定 $ go fix

    -embedlit -diff ./... $ go fix -embedlit ./new127.go $ echo $? 0 は go 1.26 → 何も出ない(正しい) # ファイル名を渡すと… # 成功したと言われる # go.mod $ go build ./... ./new127.go:43:17: use of promoted field Base.ID in struct literal of type Wrapped requires go1.27 or later (-lang was set to go1.26; check go.mod) ファイル引数は ad-hoc パッケージ扱いで go.mod の go を継がない go fix のバグではない( go build ./a.go も同じ)— golang/go#68159 は open © 2026 LOGOSWARE Corporation | 18
  18. LOGOSWARE.go#1 - Go 1.27 Release Party 数の不一致 +4 −1 =

    25 のはず。でも登録は 26 5個目は errorsastype — errors.As を errors.AsType[T] に書き換える modernizer ( errors.AsType 自体は Go 1.26 で入った stdlib) 22 $ go tool fix help | grep errorsastype # go1.27.0 errorsastype replace errors.As with errors.AsType[T] $ curl -s https://go.dev/doc/go1.27 | grep -c errorsastype 0 -var myerr *MyErr -if errors.As(err, &myerr) { +if myerr, ok := errors.AsType[*MyErr](err); ok { リリースノートに載っていない modernizer がある — 全部見るなら go tool fix help © 2026 LOGOSWARE Corporation | 19
  19. LOGOSWARE.go#1 - Go 1.27 Release Party 実戦Tips:まず -diff で確認 は成功すると

    何も言わずに 書き換える 大きなリポジトリほど、適用する前に見ておくと後が楽 直すところが残っていれば exit 1 / なければ exit 0 → CI で検知できる(落とすか警告に留めるかはチームの判断) go fix © 2026 LOGOSWARE Corporation | 20
  20. LOGOSWARE.go#1 - Go 1.27 Release Party まとめ は 1.26 で生き返り、1.27

    で +4 / −1 embedlit が示したこと 言語機能と移行ツールが同じ日に届いた go fix 明日やること、1つだけ go fix -diff ./... © 2026 LOGOSWARE Corporation | 21