Go 1.27 徹底解説 — ジェネリックメソッド解禁と encoding/json の v2 化、「壊れる」は本当か
はじめに
VictoriaMetrics が公開した「Go 1.27 interactive tour」が Hacker News で 327 ポイント・160 コメントを集め、当日のトップに立った。リリースノートを箇条書きにするのではなく、記事内でコードを動かしながら差分を確認できる形式が評価された格好だ。
Go 1.27 は 8 月リリース予定で、目玉は 2 つある。ジェネリックメソッドの解禁と、encoding/json の実装が v2 に置き換わることだ。どちらも「ついに来たか」という話題性がある一方、ネット上では「json v2 で既存コードが壊れる」という警告記事も出回っている。この記事では、この 2 つの変更の中身と、壊れる/壊れないの線引きを一次情報にあたって整理する。あわせて標準ライブラリの新パッケージと、地味だが効きそうなランタイム改善にも触れる。
ジェネリックメソッドは何を解決し、何を解決しないか
Go 1.18 でジェネリクスが入って以降、「メソッドは型パラメータを持てない」という制約が残っていた。型パラメータを取れるのはパッケージレベルの関数だけで、レシーバの型パラメータしか使えない。結果として、本来ある型に紐づくべき操作をパッケージ全体のスコープに関数として置くしかなかった。Map や FlatMap のような変換を list.Map(l, f) と書かざるを得ず、l.Map(f) にはできない、というのがよく挙げられる不満だ。
1.27 ではこれが解ける。リリースノートの表現はシンプルで、メソッド宣言がレシーバとは独立に自身の型パラメータを宣言できるようになる。パッケージ名前空間を汚さずに、型のスコープ内へジェネリックな操作を置けるようになったわけだ。
ただし、ここには外せない制約が残っている。公式リリースノートは以下のように明記している。
Note that methods of interfaces may not declare type parameters nor can interface methods be implemented by generic methods.
つまり、インターフェースのメソッドは型パラメータを宣言できず、ジェネリックメソッドでインターフェースのメソッドを満たすこともできない。理由はインターフェース充足が構造的かつ動的である点にある。Go ではある型がインターフェースを満たすかどうかは明示的な宣言ではなくメソッドセットの一致で決まり、呼び出しは実行時にディスパッチされる。そのため「そのジェネリックメソッドがどの型引数で具体化されるか」の集合を静的に閉じることができず、具体化されたコードを事前に生成する方式と噛み合わない(議論の詳細は golang/go#77273 を参照)。
実務上の意味はこうだ。「ジェネリックなメソッドを持つインターフェース」で抽象化する設計は 1.27 でも書けない。したがって 1.27 のジェネリックメソッドは「抽象化の新しい軸」ではなく、「具体型に対する記法の改善」と捉えるのが正確だ。メソッドチェーンでコレクション操作を書きたい、ビルダーに型安全な変換を足したい——そういう場面での書き味は確実に良くなる。
なお言語面ではもう 2 つ、構造体リテラルのキーに埋め込みフィールドのセレクタを書けるようになる変更(埋め込み型名を明示せず昇格フィールドを直接初期化できる)と、関数型が一致する文脈全般へ型推論が拡張される変更が入る。どちらも冗長な記述が減る方向の改善だ。
encoding/json の v2 化 —「壊れる」の正体
1.25 から実験扱いだった encoding/json/v2 が安定し、1.27 では従来の encoding/json の裏側が v2 実装に差し替わる。ここが誤解を生んでいる部分だ。
ネット上には「case-insensitive なフィールドマッチが廃止される」「nil スライスが null ではなく [] になる」といった警告が流通している。実際、byteiota の記事はこれらを「8 月までに壊れるもの」として列挙している。だが一次情報を確認すると、これらは v2 の API を直接使った場合の挙動であり、既存の v1 API を使い続ける限り適用されない。
encoding/json のパッケージドキュメントは v1 と v2 の差分を明示的に列挙したうえで、v1 の意味論を維持する設計だと説明している。ドキュメントの記述はこうだ。
In v1, JSON object members are unmarshaled into a Go struct using a case-insensitive name match with the JSON name of the fields. In contrast, v2 matches fields using an exact, case-sensitive match.
nil スライスについても同様で、v1 の Marshal は従来どおり null を出力する。v2 側にはこの差を吸収する DefaultOptionsV1() が用意されており、jsonv2.Marshal(v, json.DefaultOptionsV1()) と書けば v2 API 上で v1 の意味論を丸ごと再現できる。公式リリースノートも「v1 API は今後もサポートされ、移行は必須ではない」と述べている。
「不正な UTF-8 の拒否」「重複キーの拒否」も同じ扱いだ。リリースノートはこの厳格化を v2 パッケージの話として明示的にスコープしている。
The v2 package chooses stricter, more interoperable defaults than v1: it rejects invalid UTF-8 in JSON strings and rejects duplicate names within a JSON object.
実装を見れば裏付けが取れる。DefaultOptionsV1() が有効化するオプション一覧には jsontext.AllowInvalidUTF8(true) と jsontext.AllowDuplicateNames(true) が含まれている。つまり v1 API 経由では、不正な UTF-8 は従来どおり U+FFFD に置換されて通り、重複キーも従来どおり許容される。エラーにはならない。
では v1 ユーザーにとって本当に変わるのは何か。リリースノートの記述はこうだ。
The
encoding/jsonpackage is now backed by the v2 implementation. Marshaling and unmarshaling behavior is preserved, but the exact text of error messages may differ.
つまり実質 1 点、エラーメッセージの文言が変わることだけだ。これは地味に厄介で、エラー文字列でマッチして分岐しているコードがあれば洗い出しておきたい。逆に言えば、それ以外はマーシャル/アンマーシャルの挙動が保たれる。
性能面では、リリースノートが「Marshal はおおむね同等、Unmarshal は大幅に高速」としている。構造体へのデコードが中心のサービスなら、コード変更ゼロで恩恵を受けられる部類の改善だ。
移行チェックの手順も単純で、1.27 では v2 実装がデフォルトなので 素の go test ./... を回せばそれが差分チェックそのものになる(GOEXPERIMENT=jsonv2 は 1.25/1.26 で必要だった指定で、1.27 では既定に取り込まれており指定しても意味がない)。万一問題が出た場合は GOEXPERIMENT=nojsonv2 で旧実装に戻せる退路も用意されているが、この opt-out は将来のリリースで削除予定と明記されているので、恒久的な回避策として当てにはできない。
標準ライブラリとランタイム — 実務で効くのはどこか
言語仕様以外にも、日々のコードに効く追加がいくつかある。
uuid パッケージがトップレベルで標準入りする。RFC 9562 準拠で、暗号論的に安全な乱数を使う。uuid.NewV4()(ランダム)と uuid.NewV7()(時刻順、DB の主キー向き)が用意される点が実務的で、github.com/google/uuid を入れていた依存が 1 つ減るプロジェクトは多いはずだ。
crypto/mldsa で耐量子署名(FIPS 204 の ML-DSA)が入る。crypto/x509 が ML-DSA の秘密鍵・公開鍵・署名に対応し、crypto/tls 側には TLS 1.3 の署名スキームとして MLDSA44 / MLDSA65 / MLDSA87 の 3 定数が追加される。鍵交換側も MLKEM1024 が Config.CurvePreferences で有効化できるようになった。今すぐ全面移行する話ではないが、「harvest now, decrypt later」を懸念する領域では検証を始められる段階に来た。
メモリアロケーションの高速化も入る。80 バイト未満の小さいアロケーションについて、コンパイラがサイズ特化した確保ルーチンを生成するようになり、そのコストが最大 30% 削減される。ただしこの「30%」は数字の独り歩きに注意が必要で、リリースノートは同じ文で次のように釘を刺している。
Improvements vary depending on the workload, but the overall improvement is expected to be ~1% in real allocation-heavy programs.
つまりアロケーション処理そのものは最大 30% 速くなるが、アロケーション負荷の高い実プログラム全体で見た改善幅は 1% 程度という見積もりだ。代償はバイナリサイズが約 60 KB 増えることで、これは GOEXPERIMENT=nosizespecializedmalloc で無効化できる。コード変更なしで効くとはいえ、期待値は現実的に持っておきたい。
デバッグ周りでは goroutineleak プロファイルが runtime/pprof に追加され、/debug/pprof/goroutineleak から永久ブロックした goroutine を検出できる。実験フラグなしで使えるので、リーク調査の初手として組み込む価値がある。トレースバックに runtime/pprof の goroutine ラベルが載るようになった点も、クラッシュダンプからの原因追跡を楽にする。
そのほか、strings.CutLast() / bytes.CutLast()(最後の区切りで分割)、math/big.Int.Divide() の丸めモード指定(金額計算向け)、testing/synctest.Sleep()、httptest.NewTestServer()(実 TCP ポートを使わないインメモリサーバ)など、細かいが痒いところに届く追加が並ぶ。Unicode は 15 から 17 に上がった。
挙動変更として注意したいのは、time.After / time.NewTimer / time.NewTicker がすべてのケースで非バッファチャネルを返すようになる点(asynctimerchan GODEBUG は削除)と、http.Response.Body.Close() が接続再利用のため未読分をドレインするようになる点だ。後者は HTTP/1 でレスポンスを途中で捨てるコードの挙動に影響し得る。
まとめ
- ジェネリックメソッドは解禁されたが、インターフェースのメソッドを型パラメータ化することも、ジェネリックメソッドでインターフェースを満たすこともできない。抽象化の道具ではなく記法の改善と捉えるのが正確
encoding/jsonの v2 化で「case-insensitive が廃止」「nil スライスが[]に」「不正 UTF-8 や重複キーが弾かれる」と言われているが、これらはすべて v2 API を直接使った場合の話。DefaultOptionsV1()が互換オプションを立てるため、v1 API 経由では従来の挙動が維持される- v1 ユーザーが実際に受ける影響は、リリースノートいわくエラーメッセージの文言が変わることだけ。エラー文字列で分岐しているコードだけ確認すればよい。しかも Unmarshal は大幅に速くなる
uuidの標準入り、耐量子署名crypto/mldsa、goroutineleakプロファイルなど、コード変更なしで効く追加も多い。ただしアロケーション高速化の「最大 30%」は実プログラム全体では ~1% 程度という公式見積もりが付く
移行判断としては、素の go test ./... を一度通しておけば大半のリスクは潰せる。むしろ注目すべきは「JSON エンジンを丸ごと差し替えつつ、20 個の互換オプションで既存の意味論を丸ごと再現する」という Go チームのやり方そのものだ。ネット上に出回る「壊れる」系の警告記事の多くは v1 と v2 の API を混同しており、一次情報にあたる価値がそのまま出た事例でもある。
今日のその他のニュース
Microsoft が skill-recorder を公開 — 実際の操作手順を記録して AI エージェント向けの Skill 定義に変換する OSS。Skill や MCP で「手順をエージェントに渡す」流れが標準化しつつある中、その定義を人手で書く代わりに操作ログから生成するアプローチで、反復作業を Skill 化する初期コストを下げられる(はてブ 195)。
GKE の Managed Spark で Conda チャンネルの破壊的変更 — サブマイナーイメージ 3.5-dataproc-28 から Conda チャンネルが事前設定されなくなり、Conda 経由のパッケージインストールが失敗する。回避策は 2026-08-25 より前のイメージにピン留めするか、クラスタ初期化時に手動でチャンネルを設定すること。期限が近いので該当環境は要対応。
大阪・関西万博ドメインのドロップキャッチ — 終了イベントの関連ドメインが失効後に第三者へ取得される事例が piyolog でまとめられた。期間限定サイトの終了時にドメインをどう扱うかは、運用設計に組み込んでおくべき論点として改めて浮上している(はてブ 97)。
ソース
- Go 1.27 interactive tour - VictoriaMetrics
- Go 1.27 Release Notes - The Go Programming Language
- encoding/json package documentation
- Generic Methods Arrive in Go 1.27 - Gopher Guides
- Go 1.27 encoding/json v2: What Breaks Before August - byteiota
- Go1.27リリース連載:encoding/json/v2 - フューチャー技術ブログ
- GitHub - microsoft/skill-recorder
- 大阪・関西万博関連ドメインのドロップキャッチについてまとめてみた - piyolog