世界を動かす技術を、日本語で。

Go 1.27 インタラクティブツアー

概要

Go 1.27の主な新機能と改善点を実例付きで解説 ジェネリックメソッドや構造体リテラルの強化 標準UUIDパッケージやJSON v2のデフォルト化 パフォーマンス向上や新たなプロファイル機能 SIMDやポスト量子暗号サポートの追加

Go 1.27新機能ハンズオンガイド

  • Go 1.27 のリリース概要と背景説明

    • 公式リリースノートを元に、実用例を交えて解説
    • Anton Zhiyanovによる過去のGoツアーへの感謝
    • 本記事は公式ノートの抜粋であり、詳細は公式を参照
  • 各機能のリンク表記

    • 公式ドキュメント(𝗗)、提案(𝗣)、コミット(𝗖𝗟)、貢献者(𝗔)へのリンク付記
    • エラーハンドリングはサンプル簡略化のため省略(実際の運用では必須)

ジェネリックメソッド

  • Go 1.27 でメソッド単位の型パラメータ宣言が可能に

    • これまではトップレベル関数のみジェネリック対応
    • 型ごとに汎用的な操作をメソッドとして実装可能に
  • 利用例

    • Box[T any] structに対し、Map[U any]メソッドを実装
    • 型変換を伴う操作がメソッドとして自然に書けるように
  • 制限事項

    • インターフェースは型パラメータ付きメソッドを宣言不可
    • ジェネリックメソッドはインターフェースの満足条件に使えない

構造体リテラルのフィールドセレクタ拡張

  • 構造体リテラル でプロモートされたフィールドを直接キー指定可能に
    • 埋め込み構造体のフィールドもトップレベルと同様に扱える
    • 例:User{ID: 7, Name: "Mittens"}と簡潔に記述可能

汎用関数型推論の一般化

  • 型推論 が変数代入以外にも適用範囲拡大
    • 関数型への変換や複合リテラルでも型引数の明示不要に
    • 例:[]func([]int) int{first, last}のような書き方が可能

メモリアロケーションの高速化

  • 小規模割り当て (80バイト未満)で最大30%の高速化
    • バイナリサイズは約60KB増加
    • コード修正不要・自動適用
    • 無効化はGOEXPERIMENT=nosizespecializedmallocで可能(将来廃止予定)

ゴルーチンラベルのトレースバック表示

  • Go 1.27以降 のモジュールで、pprofラベルがトレースバックに表示
    • クラッシュやSIGQUIT時にラベル付きゴルーチンの識別が容易
    • GODEBUG=tracebacklabels=0で無効化可能(デフォルトは有効)

ゴルーチンリークプロファイル

  • runtime/pprofgoroutineleakプロファイルが実験から正式機能に
    • 永久にブロックされたゴルーチンをGCで検出しスタックを表示
    • /debug/pprof/goroutineleakエンドポイントでの監視も可能

ポスト量子署名(ML-DSA)

  • crypto/mldsa パッケージでFIPS 204準拠のML-DSA署名方式を実装
    • 3種のパラメータセット(MLDSA44, MLDSA65, MLDSA87)
    • crypto/x509crypto/tls でもサポート
    • セキュリティレベルと鍵・署名サイズのトレードオフ

標準UUIDパッケージ

  • uuid パッケージが標準ライブラリに追加
    • RFC 9562準拠、暗号論的に安全な乱数生成
    • uuid.New()で一般用途、uuid.NewV4()でランダム、uuid.NewV7()で時系列順UUID生成
    • 直接比較(==)もサポート

JSON v2がデフォルト

  • encoding/json/v2 が正式リリース、v1はv2実装で裏打ち
    • 互換性維持(エラーメッセージ等一部差異あり)
    • マップのキーはデフォルトでソートされない(高速化のため)
    • 安定した出力が必要な場合はjson.Deterministicオプションを利用

ポータブルSIMD(実験的)

  • simdパッケージ が実験的に追加(GOEXPERIMENT=simdで有効化)
    • ハードウェア依存で自動的にベクトル幅を決定
    • 型はFloat32s, Int32sなど
    • スライスからベクトルロード、演算、ストアが可能

末尾セパレータでの分割

  • strings.CutLast (および bytes.CutLast)で最後のセパレータ位置で分割
    • これまでのLastIndex利用より簡潔な記述が可能

Hackerたちの意見

今度のリリースのいくつかの例だね。 https://go.dev/doc/go1.27

このリリースでは、runtime.findnull()がAndroidのMTEと互換性を持つように修正されたよ。これが、GrapheneOSのようなMTE対応のAndroid OSでgomobileを使っているアプリでMTEを有効にするのを妨げていた唯一の要因だったんだ。 [1] https://go-review.googlesource.com/c/go/+/749062 [2] https://go-review.googlesource.com/c/go/+/751020

Golangのジェネリクスの構文、めっちゃ読みにくいよね。

ちょっと冗長だけど、推論があるおかげで「整理整頓」できるのが助かる。ジェネリクスに触れると、いつも集中力が上がる気がする。ほんとに「必要」なときだけ使うものの一つだね。

個人的には、C++の同等品よりずっと良いと思う。

そうだね、でも同時に「普通」のコードではないよね。Typescriptの高度な型に似ていて、結局は主にライブラリに存在するものだと思う。

HTTPレスポンスボディを自動で排出するのは、リスクのある静かな動作変更だと思う。ほとんどのアプリには改善になると思うけど、古い動作に頼ってた人には微妙だよね。

もう少し詳しく教えてくれる?よくわからないんだけど。

Goチームはリリースノートでそのことに触れてるよ: https://go.dev/doc/go1.27 彼らは、アイドル接続が長く残ることが許可されるユースケースにのみ影響が出ると考えてる。例えば、TransportのMaxIdleConnsを0に設定することでね。その場合は、keep aliveを無効にすることを勧めてるよ。

stdにSIMDを追加して、mapでも使えるようになるのはいいね。自分のコードのホットループで実験する場所を探さなきゃ。

Goの標準ライブラリはいつも強みだよね、特にcryptoパッケージ!素晴らしいよ。

これ: "(b Box[T]) Map[U any](f func(T) U) Box[U]" は、Goが避けてくれて嬉しかった認知的負担のタイプだね。

Hacker Newsで議論の続きを見る