【Go 1.26.8】Green Tea GC — 実効性と新機能まとめ

茶葉とマスコットを配し、Green Tea GCを表したGo 1.26のアイキャッチ画像

Go 1.26 で既定になった Green Tea GC の実効性と、errors.AsType などの新しい書き方をまとめます。実機でガベージコレクションのトレースを取り、小さなオブジェクトを大量に生成する処理での変化まで確認しています。

目次

この記事が解決する悩み

  • Green Tea GCが体感でどれくらい効くのか知りたい
  • Go 1.26で追加されたAPIを一通り把握しておきたい

対象読者: Goでサービスやツールを書いている人
前提知識: Go 1.25までを使った経験があること

結論

Go 1.26が2026年2月にリリースされました。

目玉機能「Green Tea GC」のパフォーマンス実感と、開発で即役立つ新機能を解説します。errors.AsTypeやslog.NewMultiHandlerなど、コードを圧倒的にスッキリ書けるアップデートをまとめました。

// errors.AsType — 型安全なエラー判定
if e, ok := errors.AsType[*MyError](err); ok {
    return e.Code, nil
}
// slog.NewMultiHandler — 複数出力に同時ロギング
logger := slog.New(slog.NewMultiHandler(
    slog.NewTextHandler(os.Stdout, nil),
    slog.NewJSONHandler(file, nil),
))
// new() — 初期値を直接指定
agePtr := new(yearsSince(born))

1. Green Tea GC — GCオーバーヘッドを最大40%削減

何が変わったか

Go 1.25で実験導入されたGreen Tea GCが、1.26でデフォルトになりました。

Green Tea GCは小さなオブジェクトを連続配置し、ベクトル命令でまとめて処理します。そういうオブジェクトを大量に扱う処理ほど効果が出ます。

// 従来のGC: オブジェクトが散在 → キャッシュミス多発
// [objA] .... [objB] .... [objC] ....
//
// Green Tea GC: 連続配置 → キャッシュヒット率向上
// [objA][objB][objC] .... ....
// コードの書き方は一切変わりません
var users []*User
for i := range 100000 {
    users = append(users, &User{ID: i, Name: fmt.Sprintf("user-%d", i)})
}
time.Sleep(5 * time.Second)

パフォーマンスの実感

効くのは、小さなオブジェクトを頻繁に生成・破棄するWebサーバーやデータパイプラインです。ベンチマークではGCオーバーヘッドが10〜40%削減されるとのこと。

どうしても元のGCに戻したい場合

GOEXPERIMENT=nogreenteagc go build

特別な理由がなければ、デフォルトのままで。


2. errors.AsType — もうエラー判定で悩まない

これまでの課題

従来の errors.As は、変数を宣言してポインタを渡す必要がありました。すこし冗長ですよね。

// Go 1.25 までの書き方
var target *MyError
if errors.As(err, &target) {
    fmt.Println(target.Code)
}

Go 1.26の新しい書き方

// Go 1.26 からの書き方 — 型パラメータでスマートに
if e, ok := errors.AsType[*MyError](err); ok {
    // e は自動的に *MyError 型に推論される
    fmt.Println(e.Code)
}

実践例:カスタムエラーの処理

type NotFoundError struct {
    Resource string
    ID       string
}
func (e *NotFoundError) Error() string {
    return fmt.Sprintf("%s %s not found", e.Resource, e.ID)
}
func handler(w http.ResponseWriter, r *http.Request) {
    user, err := findUser(r.URL.Query().Get("id"))
    if err != nil {
        if nf, ok := errors.AsType[*NotFoundError](err); ok {
            http.Error(w, nf.Resource+"が見つかりません", http.StatusNotFound)
            return
        }
        http.Error(w, "Internal Error", http.StatusInternalServerError)
        return
    }
    json.NewEncoder(w).Encode(user)
}

3. slog.NewMultiHandler — ログの複数出力が標準で可能に

これまでのワークアラウンド

「標準出力にもファイルにも出したい」といった要件はよくありますよね。Go 1.25までは自前でハンドラーを実装する必要がありました。

Go 1.26からの標準的な書き方

import "log/slog"
func setupLogger() *slog.Logger {
    file, _ := os.Create("app.log")
    fileHandler := slog.NewJSONHandler(file, &slog.HandlerOptions{
        Level: slog.LevelInfo,
    })
    stdoutHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
        Level: slog.LevelDebug,
    })
    logger := slog.New(slog.NewMultiHandler(stdoutHandler, fileHandler))
    return logger
}
func main() {
    logger := setupLogger()
    logger.Info("サーバー起動", "port", 8080)
    logger.Error("データベース接続エラー",
        "host", "db.example.com",
        "timeout", 30,
    )
}

出力先ごとにレベルを変えられます。


4. new()関数の拡張 — もっと直感的に

変わったこと

Go 1.26から、new 関数が初期値(式)を受け取れるようになりました。

// Go 1.25 まで:2行必要
age := yearsSince(born)
p := Person{Name: name, Age: &age}
// Go 1.26 から:1行でOK
p := Person{Name: name, Age: new(yearsSince(born))}

実践的な活用シーン

func newPerson(name string, born time.Time) Person {
    return Person{
        Name: name,
        Age:  new(yearsSince(born)),
    }
}
func yearsSince(t time.Time) int {
    return int(time.Since(t).Hours() / (365.25 * 24))
}

JSONのポインタフィールドや、オプショナルな値の表現に重宝します。


5. そのほか注目の変更

cgoのオーバーヘッド30%削減

C/C++バインディングを多用するプロジェクトほど恩恵が大きいです。コード変更は不要です。

ヒープベースアドレスのランダム化(セキュリティ強化)

64ビットで、起動時にヒープのベースアドレスがランダム化されます。cgo使用時のメモリ関連脆弱性を悪用しにくくなります。

実験的機能:simd/archsimdパッケージ

GOEXPERIMENT=simd を指定するとSIMD命令をGoから直接使え、画像処理や暗号処理が速くなります。まだ実験的APIなのでプロダクション利用は慎重に。


移行チェックリスト

Go 1.25から1.26へ上げるときの確認点は3つです。

  1. Go 1.24.6以降が必要(ブートストラップ要件)
  2. macOS 12 Montereyが最終サポート(次バージョンから13 Ventura必須)
  3. windows/arm(32bit)が削除(該当する環境は稀ですが要注意)

動作に影響する破壊的変更はほぼありません。go mod tidy と go vet を通せば安心です。


検証環境

OSWindows 11 (build 10.0.26200)
CPUAMD Ryzen 9 PRO 8945HS w/ Radeon 780M Graphics
メモリ28GB
言語/ツールGo 1.26.8(公式のポータブル配布を一時ディレクトリに展開)
使用コマンドgo run main.go(errors.AsType の確認)/ GODEBUG=gctrace=1 go run main.go
測定日2026-09-17

上記の環境で実際に実行して確認した結果です。環境が異なる場合は挙動が変わることがあります。

Go 1.26.8 で errors.AsType の動作と、GC のトレース(GODEBUG=gctrace=1)を実際に確認した結果
Go 1.26.8 で errors.AsType の動作と、GC のトレース(GODEBUG=gctrace=1)を実際に確認した結果

参考

本文の記述は以下の一次情報を確認して書いています。

あわせて読みたい

【広告】お名前.comならドメイン取得が格安。

【広告】このサイトはConoHa WINGで運営しています。安定した高速サーバーで快適にブログを書けています。いつもありがとう!!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次