Go 1.27 は 2026 年 8 月 19 日にリリースされ、ジェネリックメソッド(メソッドが自分の型パラメータを持てる)が使えるようになりました1 2 。標準ライブラリには uuid と encoding/ json/ v2 が入り、go fix には新しい modernizer(古い書き方を新しい書き方に置き換える解析器)が 4 つ増えています1 。移行は「go.mod を上げる → go fix を回す → テストする」の 3 段で大半が終わり、go fix が扱わない書き換えや影響調査を Claude Code に任せると速く進みます。この記事では Go 1.27.1 を実際に入れて新機能と移行手順を動かし、出力をそのまま載せます。
Go 1.27 は Go 1.26 から 6 か月後のメジャーリリースで、Go 1 の互換性の約束を保ったまま言語・ツール・ランタイム・標準ライブラリが更新されました1 。2026 年 10 月時点の最新は 2026 年 9 月 1 日の Go 1.27.1 です3 。
変更点を、移行作業に影響する順に並べると次のとおりです。
区分 主な変更 移行への影響 言語 ジェネリックメソッド、構造体リテラルで埋め込みフィールドをキーに書ける、関数の型推論が全ての代入文脈に拡大 go.mod の go を 1.27 にしたファイルで使える ツール go fix に modernizer 4 つ追加、go test が stdversion を既定で検査、go doc pkg@version古い書き方の一括更新に使える ランタイム 80 バイト未満の小さな割り当てが最大 30% 速い、goroutineleak プロファイルが正式機能に 何もしなくても効く 標準ライブラリ uuid、encoding/ json/ v2、encoding/ json/ jsontext、crypto/ mldsa が新設外部ライブラリを置き換えられる 削除・終了 asynctimerchan などの GODEBUG を完全削除、macOS 12 以前のサポート終了古い設定に頼っていたら要対応
ランタイムの改善は、小さな割り当て(80 バイト未満)のコストを最大 30% 下げ、割り当ての多いプログラム全体では約 1% 速くなるというものです1 。そのぶんバイナリは約 60KB 増えます1 。
Go のサポートは「最新の 2 つのメジャーリリース」までで、Go 1.27 が出た時点で Go 1.25 はセキュリティ修正の対象から外れています3 。Go 1.25 以前のまま運用しているなら、今が上げどきです。
検索の関心も伸びています。Google トレンド(日本・過去 90 日、2026-10-05 取得)の相対値で、「Go言語」は直近 4 週の平均が 2.0、その前の 8 週の平均が 0.3 でした。値は小さいものの上向きです4 。
「Go言語」の検索の関心(日本・Google トレンドの相対値) データを表で見る 「Go言語」の検索の関心(日本・Google トレンドの相対値) 期間 Go言語 前 8 週の平均 0.3 直近 4 週の平均 2
出典: Google トレンド(日本・過去 90 日、2026-10-05 取得)の相対値。同じ回の基準語 GitHub Copilot の直近 4 週平均は 26.7
もう 1 つの理由は、Go 1.26 で刷新された go fix が 1.27 でさらに強くなったことです。手作業で書き換えていた古い書き方の多くを、ボタン 1 つで直せるようになりました。
既存の Go を残したまま Go 1.27 を試すには、golang.org/ dl のラッパーを使います。macOS・Linux・Windows で同じ手順です。
go install golang.org/dl/go1.27.1@latest
go1.27.1 download
go1.27.1 version
go version go1.27.1 darwin/amd64
筆者の環境(macOS、Go 1.26.2)ではこの 3 行で入りました。go1.27.1 というコマンドが ~/ go/ bin にでき、本体は ~/ sdk/ go1.27.1 に展開されます。
macOS では Go 1.27 から macOS 13 Ventura 以降が必要です1 。古い Mac の CI ランナーを使っているなら先に確認してください。
ジェネリックメソッドとは、型パラメータを持つ型のメソッドが、さらに自分だけの型パラメータを宣言できる機能です。これまでは型パラメータをパッケージ関数にしか書けず、Map のような変換は関数として書くしかありませんでした。
次のコードは Go 1.27.1 で go vet と go run が通ることを確かめたものです。
type Set[T comparable] struct {
m map [T]struct {}
}
func (s *Set[T]) Map[U comparable](f func (T) U) *Set[U] {
out := NewSet[U]()
for x := range s.m {
out.m[f(x)] = struct {}{}
}
return out
}
words := NewSet("go" , "rust" , "zig" , "gleam" )
lens := words.Map(func (s string ) int { return len (s) })
標準ライブラリでは math/ rand/ v2 の (*Rand).N がジェネリックメソッドになりました1 。r.N(int64(100)) のように、トップレベルの rand.N と同じ感覚で使えます。
制約が 2 つあります1 。
インタフェースのメソッドは型パラメータを宣言できない
ジェネリックメソッドでインタフェースのメソッドを実装することはできない
go.mod の go が 1.26 のままだと、Go 1.27 のコンパイラでもエラーになります。
./a.go:5:21: generic method requires go1.27 or later (-lang was set to go1.26; check go.mod)
Go 1.26.2 のコンパイラでは syntax error: method must have no type parameters になりました。
構造体リテラルのキーに、埋め込みフィールドの中のフィールドを直接書けるようになりました1 。
type Meta struct { Owner string }
type Item struct {
Meta
Name string
}
it := Item{Owner: "kohei" , Name: "demo" }
Go 1.26.2 では unknown field Owner in struct literal of type Item でした。Go 1.27.1 で go.mod が 1.26 のままだと use of promoted field Meta.Owner in struct literal of type Item requires go1.27 or later と言われます。
関数の型推論も広がり、ジェネリック関数を関数型の変数に代入する全ての場面で型引数を省けます1 2 。
func Double [T int | float64 ](x T) T { return x * 2 }
fs := []func (int ) int {Double}
g := (func (float64 ) float64 )(Double)
ch := make (chan func (int ) int , 1 )
ch <- Double
この 3 行は Go 1.26.2 ではいずれも cannot use generic function Double without instantiation でした。Go 1.27.1 では通り、42 3 10 が出力されます。
新しいパッケージで影響が大きいのは uuid と encoding/ json/ v2 です1 。
パッケージ 中身 置き換えられるもの uuidUUID の生成と解析(RFC 9562)。New・NewV4・NewV7・Parse・MustParse 外部の UUID ライブラリ encoding/ json/ v2Marshal・Unmarshal などに Options を渡せる新しい JSONencoding/ json(v1 も引き続き使える)encoding/ json/ jsontextトークン単位の低レベル処理 自前のストリーム処理 crypto/ mldsa耐量子署名 ML-DSA(FIPS 204) — strings.CutLast / bytes.CutLast最後の区切りで分ける strings.LastIndex と添字の組み合わせ
実際に動かしたコードと出力です。
import (
"encoding/json/v2"
"strings"
"uuid"
)
id := uuid.NewV7()
dir, file, ok := strings.CutLast("internal/app/handler.go" , "/" )
b, err := json.Marshal(struct {
Name string `json:"name"`
Tags []string `json:"tags"`
}{Name: "go1.27" , Tags: nil })
internal/app handler.go true
{"name":"go1.27","tags":[]} <nil>
encoding/ json/ v2 は nil のスライスを null ではなく [] にしました。v2 は不正な UTF-8 や重複したキーも既定で拒否します1 。v1 の API はそのまま残り、移行は必須ではありません1 。import を v2 に変える前に、出力 JSON を比べるテストを書いておくと安全です。
go fix は Go 1.26 で作り直され、「modernizer」の置き場になりました5 。modernizer は、プログラムの動きを変えずに新しい言語機能や標準 API へ書き換える解析器です5 。go vet と同じ解析フレームワークの上に作られています5 。
Go 1.27 では atomictypes・embedlit・slicesbackward・unsafefuncs が加わり、fmtappendf が外れ、waitgroup は waitgroupgo に名前が変わりました1 。手元の go tool fix help に出る解析器の数を数えると、次のようになりました。
go tool fix help に出る解析器の数(Go のバージョン別) データを表で見る go tool fix help に出る解析器の数(Go のバージョン別) バージョン 解析器の数(個)(個) Go 1.26.2 22 Go 1.27.1 26
出典: 筆者計測(2026-10-05、macOS で go tool fix help の Registered analyzers を数えた)
Go 1.27.1 の一覧には、リリースノートの 4 つのほかに errorsastype(errors.As を errors.AsType[T] に置き換える)も出ていました。
modernizer は go.mod の go の値(またはファイルの / / go:build go1.N)を見て、そのバージョンで使える書き換えだけを行います5 。go.mod を先に上げるか後に上げるかで結果が変わるのはこのためです。
移行は「機械的に直せる部分は go fix、判断が要る部分は Claude Code、最後にテスト」と分けます。全体の流れは次の図のとおりです。
Go 1.27 への移行を、go.mod の更新、go fix、Claude Code による残りの書き換え、テストの 4 段で進める流れ 図: 筆者作成
go fix の差分だけがコミットに入るよう、変更の無い状態から始めます。Go チームのブログもこれを勧めています5 。
git switch -c go1.27
git status --short
go1.27.1 get go@1.27.0
go: upgraded go 1.25 => 1.27.0
go 1.27 以上のモジュールでは、go mod tidy が重複した require ブロックを直接依存と間接依存の 2 つまでにまとめます1 。go.mod の差分が増えても慌てないでください。
-diff を付けると、ファイルを書き換えずに差分だけを出します。差分があると終了コードが 0 以外になります。
go1.27.1 fix -diff ./...
go1.27.1 fix ./...
go1.27.1 fix -diff ./...
1 つの書き換えが次の書き換えを生むことがあるので、差分が出なくなるまで繰り返します5 。GOOS や GOARCH ごとのファイルがあるなら、値を変えて複数回回します5 。
検証用の小さなパッケージ(go.mod は go 1.25)に実行した結果の一部です。
type Counter struct {
- hits int64
+ hits atomic.Int64
}
-func (c *Counter) Inc() { atomic.AddInt64(&c.hits, 1) }
+func (c *Counter) Inc() { c.hits.Add(1) }
- for i := len(xs) - 1; i >= 0; i-- {
- out = append(out, xs[i])
+ for _, x := range slices.Backward(xs) {
+ out = append(out, x)
- wg.Add(1)
- go func() {
- defer wg.Done()
+ wg.Go(func() {
- return Doc{Meta: Meta{Owner: owner}, Title: title}
+ return Doc{Owner: owner, Title: title}
- var pe *fs.PathError
- if errors.As(err, &pe) {
+ if pe, ok := errors.AsType[*fs.PathError](err); ok {
embedlit(埋め込みフィールドのキー)と errorsastype の書き換えは、go.mod を上げる前の -diff には出ず、go 1.27.0 に上げた後にだけ出ました。バージョンに合わせて書き換えを選ぶ仕組みが、そのまま見えています。
特定の解析器だけを動かすときは -NAME を付け、外すときは -NAME=false を付けます5 。
go1.27.1 fix -any -rangeint ./...
go1.27.1 fix -stringsbuilder=false ./...
go1.27.1 vet ./...
go1.27.1 test -race ./...
git diff --stat
ok example.com/legacy 3.367s
go.mod | 2 +-
legacy.go | 37 +++++++++++++++----------------------
2 files changed, 16 insertions(+), 23 deletions(-)
ここまでの流れを録画したものです(出力は実際の実行結果)。
Go 1.27.1 で go.mod を上げ、go fix で書き換え、go test -race で確認するまでのターミナル操作 実際の実行結果を録画。macOS・Go 1.27.1
go fix は「動きを変えない書き換え」しかしません5 。外部ライブラリから標準の uuid への置き換えや、encoding/ json/ v2 に変えたときの出力差の確認は、人か AI エージェントの判断が要ります。ここを Claude Code に任せます。
Claude Code には -p(--print)で 1 回だけ指示を渡して終わるモードがあり、--allowedTools で許可なしに使えるツールを絞れます6 。次の例は、調査だけを読み取り系のコマンドに限って頼むものです。
claude -p "Go 1.27 への移行を手伝って。
1. go.mod と //go:debug に、Go 1.27 で削除された GODEBUG(asynctimerchan, tlsrsakex, tls3des, tls10server, tlsunsafeekm, x509keypairleaf, gotypesalias)が無いか探す
2. github.com/google/uuid の使用箇所を一覧にし、標準の uuid に置き換えられるか判定する
3. 結果を表にまとめる。ファイルはまだ変更しない" \
--allowedTools "Read" "Grep" "Glob" "Bash(go list *)" "Bash(git grep *)"
調査の結果を見て置き換えると決めたら、対話モードで頼みます。Claude Code の公式ベストプラクティスは、Claude に結果を確かめる手段(テスト・ビルド・リンター)を渡すことを勧めています7 。指示の最後に「go1.27.1 test -race ./ ... が通るまで直して」と書き、検証の手段を渡します。
> github.com/google/uuid を標準の uuid パッケージに置き換えて。
uuid.New() の戻り値の型が変わる箇所は呼び出し側も直す。
最後に go1.27.1 vet ./... と go1.27.1 test -race ./... が通ることを確かめて。
編集のたびに gofmt や go test を自動で走らせたいなら、Claude Code の hooks が使えます。設定例は Claude Code で Go のテスト駆動開発 にまとめました。プロジェクトの約束ごと(使う Go のバージョン、go1.27.1 コマンドを使うことなど)は CLAUDE.md に書いておくと毎回伝えずに済みます。書き方は CLAUDE.md の書き方 を参照してください。
上げる前に確認しておきたい点は 5 つです1 。
削除された GODEBUG : asynctimerchan が完全に削除され、time パッケージのチャネルは常に同期になりました。tlsrsakex・tls3des・tls10server・tlsunsafeekm・x509keypairleaf・gotypesalias も削除です。go.mod の godebug や / / go:debug に古い値が残っているとビルドが失敗します
gofmt の空白の変化 : 桁揃えの処理が直され、整形済みのコードでも空白が少し変わることがあります。整形だけのコミットを分けると、レビューが楽になります
go test が stdversion を検査する : go.mod の Go バージョンより新しい標準ライブラリの関数を使うと、go test で報告されます
compress/ flate の出力が変わる : 圧縮が速くなった代わりに、出力のバイト列が 1.26 と変わることがあります。gzip や PNG の出力をバイト単位で比べるテストは落ちる可能性があります
関数リテラルの名前が短くなる : クロージャのシンボル名を前提にしたテストは更新が必要です
go tool trace -http=:6060 のようにポートだけを渡すと、Go 1.27 からは localhost でしか待ち受けません1 。他のマシンから見たいときは -http=0.0.0.0:6060 と書きます。
Go 1.27 は 2026 年 8 月 19 日リリース。2026 年 10 月時点の最新は 1.27.1
言語はジェネリックメソッド、構造体リテラルの埋め込みフィールドキー、型推論の拡大が入った
標準ライブラリに uuid と encoding/ json/ v2 が入り、外部ライブラリを減らせる
移行は「go.mod を上げる → go fix を収束するまで回す → go test -race」で大半が終わる
go fix が扱わない置き換えと影響調査は、テストという確認手段を付けて Claude Code に任せる
次にやることは、手元のモジュールで go1.27.1 fix -diff ./ ... を 1 回実行して、どれだけ書き換えが出るかを見ることです。Go と AI エージェントの組み合わせ全般は Go 言語と AI エージェントの相性 で解説しています。
2026 年 8 月 19 日です2 3 。最初のマイナーリリース Go 1.27.1 は 2026 年 9 月 1 日に出ています3 。
できません。インタフェースのメソッドは型パラメータを持てず、ジェネリックメソッドでインタフェースのメソッドを実装することもできません1 。
modernizer は動きを変えない書き換えだけを行う設計です5 。それでも念のため、きれいな git の状態から始め、適用後に go test -race ./ ... を回してください。問題があれば Go の issue に報告するよう案内されています5 。
必須ではありません。v1 の API はそのまま残ります1 。v2 は nil スライスの扱いや重複キーの拒否など既定の動きが違うので、移すなら出力を比べるテストを先に用意します。
使えます。go fix の刷新は Go 1.26 からです5 。ただし atomictypes・embedlit・slicesbackward・unsafefuncs は Go 1.27 で入った modernizer なので、Go 1.27 のツールチェーンが必要です1 。