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

What's new in Go 1.26?

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

What's new in Go 1.26?

Avatar for Koya IWAMURA

Koya IWAMURA

February 25, 2026
Tweet

More Decks by Koya IWAMURA

Other Decks in Technology

Transcript

  1. new() 関数の拡張 組み込み関数new が拡張され、式を渡して初期値を指定できるようになっ た // 従来 p := new(int)

    *p = 42 // Go 1.26から:式を渡して初期値を指定 p := new(42) fmt.Println(*p) // 42 encoding/json などでオプショナル値をポインタで表現する際に便利 type User struct { Email *string `json:"email,omitempty"` } 4
  2. 再帰的な型制約(2/2) func (pq *PriorityQueue[T]) Push(item T) { for i, existing

    := range pq.items { if item.CompareTo(existing) < 0 { // pq.itemsのiの位置にitemを追加 return } } // pq.itemsの末尾にitemを追加 } func (pq *PriorityQueue[T]) Pop() (T, bool) { /* 省略 */ } type Task struct { name string priority int } func (t Task) CompareTo(other Task) int { return cmp.Compare(t.priority, other.priority) } // 使用例 pq := &PriorityQueue[Task]{} pq.Push(Task{"Low priority", 1}) pq.Push(Task{"High priority", 10}) pq.Push(Task{"Medium priority", 5}) task, _ := pq.Pop() // Task{"High priority", 10}が取り出される 6
  3. go mod init のデフォルトバージョン変更 go mod init で作成されるgo.mod のデフォルトgo バージョンが変更

    バージョン1.N.X のツールチェーンはgo 1.(N-1).0 を指定 ツールチェーン go.mod に記載されるバージョン Go 1.26 RC go 1.24.0 Go 1.26.X go 1.25.0 現在サポートされているGo バージョンとの互換性を保ちやすくなる 自身で変更したい場合はgo get go@version 7
  4. go fix の刷新 go fix が全面的に書き換えられ、コード自動修正機能を強化 golang.org/x/tools/go/analysis を利用(go vet と同様)

    # すべてのアナライザを実行 go fix . # 特定のアナライザを指定 go fix -forvar . # 変更を適用せず差分表示 go fix -diff . # 登録されているアナライザを表示 go tool fix help # forvarの説明を表示 go tool fix help forvar 8
  5. go fix の刷新 - 組み込みアナライザ アナライザ 説明 buildtag 古い //+build

    コメントを検出し //go:build 形式に修正 hostport fmt.Sprintf("%s:%d", host, port) をIPv6 対応の net.JoinHostPort に修正 inline //go:fix inline 指定の関数呼び出しをインライン展開 modernize.Suite 複数のモダナイザをまとめた集合 9
  6. go fix の刷新 - modernize.Suite の主なモダナイザ モダナイザ 説明 errorsastype errors.As

    を errors.AsType[T] に置換 newexpr &T{} を new(T) に置換 omitzero json:",omitempty" を omitzero タグの統合 forvar ループ変数のコピーを削除 mapsloop maps パッケージの関数を使うよう置換 waitgroup wg.Add(1) + defer wg.Done() を wg.Go に置換 そのほかにも様々ある https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize 10
  7. Green Tea GC Go 1.25 で実験的に導入されたGreen Tea GC がデフォルトで有効に メモリ局所性とCPU

    スケーラビリティを向上 GC オーバーヘッドが10 〜40% 削減 新しいamd64 CPU (Intel Ice Lake / AMD Zen 4 以降)でベクトル命令を 活用 小さなオブジェクトのスキャンがさらに約10% 高速化 12
  8. cgo 呼び出しの高速化 cgo 呼び出しのベースラインランタイムオーバーヘッドが約30% 削減 変更の概要 Go 1.25 以前: goroutine

    がcgo 呼び出しを行う際、専用の_Psyscall 状態を 使用 P はgoroutine に関連付けられたまま待機し、他のgoroutine が使えない Go 1.26 以後: この特殊な状態を削除 cgo 呼び出し開始時にP を即座に解放 他の実行可能なgoroutine がすぐにP を使用可能 13
  9. simd/archsimd — 命令の一例 ロード / ストア // src[i:i+16] = [1.0,

    2.0, 3.0, ...] v := archsimd.LoadFloat32x16Slice(src[i:i+16]) v.StoreSlice(dst[i:i+16]) // dst[i:i+16] == [1.0, 2.0, 3.0, ...] 算術(加算・減算・乗算・除算) // va = [1,2,3,4,...], vb = [10,20,30,40,...] res := va.Add(vb) // res == [11,22,33,44,...] res = va.Sub(vb) // res == [-9,-18,-27,-36,...] res = va.Mul(vb) // res == [10,40,90,160,...]s res = va.Div(vb) // res == [0.1,0.1,0.1,0.1,...] 18
  10. ドット積(内積) // va = [1,2,3,4], vb = [10,20,30,40] prod :=

    va.Mul(vb) // prod == [10,40,90,160] sum := prod.HorizontalAdd() // sum == 10+40+90+160 == 300 ビット演算(AND/OR/XOR/NOT ) // va = [0b1100, 0b1010], vb = [0b0110, 0b0011] and := va.And(vb) // and == [0b0100, 0b0010] or := va.Or(vb) // or == [0b1110, 0b1011] xor := va.Xor(vb) // xor == [0b1010, 0b1001] not := va.Not() // not == [0b0011, 0b0101] そのほか多種多様な命令がサポートされています https://pkg.go.dev/simd/archsimd 19
  11. runtime/secret パッケージ(実験的サポート) GOEXPERIMENT=runtimesecret で有効(Linux AMD64/ARM64 ) 秘匿処理に使用した一時ストレージを安全に消去 func DeriveSessionKey(peerPublicKey *ecdh.PublicKey)

    ([]byte, error) { var sessionKey []byte secret.Do(func() { // 一時的な秘密鍵・共有秘密をこのスコープ内で生成 privKey, _ := ecdh.P256().GenerateKey(rand.Reader) sharedSecret, _ := privKey.ECDH(peerPublicKey) // 関数終了時にprivKeyとsharedSecretが安全に消去される sessionKey = performHKDF(sharedSecret) }) return sessionKey, nil } 20
  12. errors.AsType errors.As のジェネリック版が追加 リフレクションを使用せずerrors.As より高速 変数スコープを狭められる // errors.As を使用(従来) var

    target *MyError if errors.As(err, &target) { fmt.Println("error:", target) } // errors.AsType を使用 if target, ok := errors.AsType[*MyError](err); ok { fmt.Println("error:", target) } 21
  13. log/slog.NewMultiHandler 複数のHandler を同時に呼び出すMultiHandler を作成 // 標準出力とファイルの両方にログを出力 stdoutHandler := slog.NewTextHandler(os.Stdout, nil)

    file, _ := os.OpenFile("/tmp/app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) fileHandler := slog.NewJSONHandler(file, nil) multiHandler := slog.NewMultiHandler(stdoutHandler, fileHandler) logger := slog.New(multiHandler) logger.Info("login", slog.String("name", "whoami"), slog.Int("id", 42), ) 22
  14. bytes.Buffer.Peek バッファを進めずに次のn バイトを返すPeek メソッドが追加 buf := bytes.NewBufferString("Hello, bytes") sample, err

    := buf.Peek(5) fmt.Printf("peek=%s err=%v\n", sample, err) // peek=Hello err=<nil> buf.Next(7) // "Hello, "をスキップ sample, err = buf.Peek(5) fmt.Printf("peek=%s err=%v\n", sample, err) // peek=bytes err=<nil> 23
  15. os/signal.NotifyContext の改善 どの信号を受信したかをcontext.Cause で取得できるように ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer

    stop() <-ctx.Done() fmt.Println("err =", ctx.Err()) // err = context canceled fmt.Println("cause =", context.Cause(ctx)) // cause = signal: interrupt 25
  16. net/http/httptest : example.com のリダイレクト対応 httptest.Server のクライアントが example.com (とそのサブドメイン) へのリクエストをテストサーバーにリダイレクトするように テスト用ハンドラをドメイン名でそのままテストできる

    srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello")) })) defer srv.Close() // example.com へのリクエストがテストサーバーに届く resp, err := srv.Client().Get("https://example.com") body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) // hello 29
  17. net/netip : Prefix.Compare 2 つのプレフィックスを比較する Prefix.Compare メソッドが追加 slices.SortFunc にそのまま渡せる 優先度順

    1. 妥当性: 無効なプレフィックスが先、有効が後 2. アドレスファミリ: IPv4 が IPv6 より先 3. マスクされたIP アドレス: ネットワークアドレス(例: 10.0.0.0 )の数値 順 4. プレフィックス長: 短い方が先(例: /8 → /16 → /24 ) 5. マスクされていないアドレス: 元のIP アドレスの数値順 30
  18. net/url : 不正なURL を拒否するように url.Parse がホスト部分にコロンを含む不正なURL をエラーにするように // 以前は通っていたが Go

    1.26 からエラー _, err := url.Parse("http://::1/") fmt.Println(err) // invalid URL _, err = url.Parse("http://localhost:80:80/") fmt.Println(err) // invalid URL // IPv6 アドレスを角括弧で囲めば OK u, _ := url.Parse("http://[::1]/") fmt.Println(u.Host) // [::1] 31
  19. runtime/metrics : 新しいスケジューラメトリクス goroutine の状態別カウントやOS スレッド数などが取得できるように // 追加されたメトリクス // /sched/goroutines-created:goroutines

    作成された goroutine 総数 // /sched/goroutines/runnable:goroutines 実行可能状態 // /sched/goroutines/running:goroutines 実行中 // /sched/goroutines/waiting:goroutines 待機中 // /sched/threads/total:threads OS スレッド数 samples := []metrics.Sample{ {Name: "/sched/goroutines/runnable:goroutines"}, {Name: "/sched/threads/total:threads"}, } metrics.Read(samples) fmt.Println(samples[0].Value.Uint64()) // 実行可能 goroutine 数 fmt.Println(samples[1].Value.Uint64()) // OS スレッド数 32
  20. Appendix Go 1.26 Release Notes - The Go Blog Go

    1.26 interactive tour - Anton Zhiyanov 33