---
title: "Go 1.25の新機能と変更点｜サポート終了後の脆弱性と1.24から上げると変わる箇所を実測"
url: "https://www.issoh.co.jp/tech/details/8421/"
published: 2025-08-26
updated: 2026-10-31
categories: ["Go"]
publisher: "株式会社一創"
---

# Go 1.25の新機能と変更点｜サポート終了後の脆弱性と1.24から上げると変わる箇所を実測

Go 1.25は2025年8月12日に公開されたリリースです（[Go 1.25リリースノート](https://go.dev/doc/go1.25)）。言語仕様の変更はなく、ランタイム・ツール・標準ライブラリの更新が中心ですが、1.24から上げると**エラー確認前にポインタを触るコードがpanicする**、**go.modのgo行によってGOMAXPROCSの既定値が変わる**といった、動作に出る変更が含まれます。この記事では、go1.24.13とgo1.25.14で同じコードを実行した出力を並べて、移行時に確かめる箇所と主要な新機能を説明します。

Go 1.25は2026年8月19日のGo 1.27公開でサポートが終わり、その後に出たセキュリティ修正は1.25系に入っていません。現行版の変更点と更新手順は[Go 1.27の新機能・変更点まとめ](/tech/details/10416/)にまとめています。Go自体の導入から始める場合は[Go言語の実装入門](/tech/details/17483/)が入口です。

## まとめ：Go 1.25で押さえる要点

- リリースは2025年8月12日、最終パッチは2026年8月19日のgo1.25.14。以後のセキュリティ修正は1.26系・1.27系にしか出ておらず、HTTPサーバーを動かす検証コードをgovulncheckで調べると、呼び出し経路のある未修正の脆弱性が8件見つかりました。
- Go 1.21〜1.24のコンパイラにあったnilチェック遅延のバグが直り、`err`を確かめる前に戻り値のポインタを使うコードがpanicします。go.modのgo行が1.24のままでも起きます。
- 要素数が変数の`make`もスタックに置かれるようになり、32バイトの一時スライスはヒープ割り当てが0回になりました。`unsafe.Pointer`の誤用が表に出やすくなる変更でもあります。
- コンテナのCPU上限に合わせたGOMAXPROCS、TLS 1.2のSHA-1署名拒否などは、go.modのgo行が1.25以上のときだけ有効です。ツールチェーンを上げただけでは切り替わりません。
- `testing/synctest`が正式機能になり、1時間待つテストを仮想時計で即座に終えられます。`sync.WaitGroup.Go`とgo vetの`waitgroup`・`hostport`も追加されました。
- 実験機能だったGreen Tea GCはGo 1.26で既定に、`encoding/json/v2`はGo 1.27で正式版になりました。1.25で試すときの切り替え方は後続版と違います。

以下、移行時に挙動が変わる箇所から順に説明します。

## Go 1.25のサポート終了日と終了後に残る脆弱性

Goは「各メジャーリリースは、2つ新しいメジャーリリースが出るまでサポートする」方針です（[Goのリリース履歴](https://go.dev/doc/devel/release)）。1.25はGo 1.27が出た2026年8月19日にサポートが終わり、それ以降の修正は1.26系と1.27系にだけ出ています。

### リリース日とサポート終了日

| 版                  | 公開日        | 1.25にとっての意味  |
| ------------------ | ---------- | ------------ |
| go1.25.0           | 2025-08-12 | 初版           |
| go1.26.0           | 2026-02-10 | 1.25はサポート中   |
| go1.25.14          | 2026-08-19 | 1.25系の最後のパッチ |
| go1.27.0           | 2026-08-19 | 1.25のサポート終了  |
| go1.26.9・go1.27.2  | 2026-10-08 | 1.25系には修正なし  |
| go1.26.10・go1.27.3 | 2026-10-19 | 1.25系には修正なし  |

### govulncheckで見るgo1.25.14の未修正脆弱性

サポート終了の影響を数で見るため、`http.ListenAndServe`と`x509.ParseCertificate`を呼ぶだけの小さなプログラムを、go.modのgo行を1.25にして[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck) v1.9.0（脆弱性データベースは2026年10月27日更新）で調べました。

```
$ GOTOOLCHAIN=go1.25.14 govulncheck ./...
Vulnerability #1: GO-2026-6809
    Distrust compromised intermediate certificates in crypto/x509
  Standard library
    Found in: crypto/x509@go1.25.14
    Fixed in: crypto/x509@go1.26.10

Vulnerability #2: GO-2026-6617
    HTTP/2 server crash due to HPACK encoder race in net/http
  Standard library
    Found in: net/http@go1.25.14
    Fixed in: net/http@go1.26.9
（中略）
Your code is affected by 8 vulnerabilities from the Go standard library.

$ GOTOOLCHAIN=go1.27.3 govulncheck ./...
No vulnerabilities found.
```

呼び出し経路のある8件のうち7件はnet/http・crypto/tls・mime/multipartの脆弱性で2026年10月8日のgo1.26.9、1件はcrypto/x509の脆弱性で10月19日のgo1.26.10が修正版です。たとえば[GO-2026-6809](https://pkg.go.dev/vuln/GO-2026-6809)の影響範囲は「go1.26.10より前、およびgo1.27.0以上go1.27.3未満」で、1.25系の修正版はありません。同じコードをgo1.27.3で調べると0件でした。HTTPサーバーを公開しているサービスで1.25.14を使い続けると、今後その版にも影響する脆弱性が見つかっても、Goプロジェクトから修正版が提供されません。

注意点として、govulncheck v1.9.0はgo.modで`go 1.26.0`を要求します。`GOTOOLCHAIN=go1.25.14`のまま`go install`すると`requires go >= 1.26.0`で入らないため、1.26以降でインストールし、調べるときだけ対象のツールチェーンへ切り替えます。終了コードの扱いやCIへの組み込みは[govulncheckの使い方【v1.9.0】終了コード・ignore代替・Actions設定](/tech/details/3013/)で説明しています。

### Cloud Run・App Engineのgo125ランタイムの期限

Google Cloudのマネージドランタイムには、Go本体とは別の期限があります。次の表のCloud Runの期限はGoogle管理のベースイメージを使うワークロードが対象で、独自のコンテナイメージを直接デプロイする場合には適用されません。

| サービス             | ランタイムID | 1つ目の期限            | 2つ目の期限         |
| ---------------- | ------- | ----------------- | -------------- |
| Cloud Run        | go125   | 非推奨 2026-10-01    | 廃止 2027-04-01  |
| App Engineスタンダード | go125   | サポート終了 2027-03-02 | 非推奨 2028-03-02 |

[Cloud Runのランタイムサポート表](https://cloud.google.com/run/docs/runtime-support)では、go125は2026年10月1日に非推奨期間へ入っており、2027年4月1日の廃止以降は、このランタイムでワークロードを新規作成・更新できないと書かれています。[App Engineのサポートスケジュール](https://cloud.google.com/appengine/docs/standard/lifecycle/support-schedule)はgo125のサポート終了を2027年3月2日としています。どちらもGo本体のサポート終了より後ですが、延びるのはデプロイできる期間で、Goプロジェクトが1.25系の修正版を出さない点は変わりません。期限が近いCloud Runのサービスから、go126かgo127へ切り替えるのが安全な順番です。

複数のサービスでGoの版がそろっていない場合は、go.modのgo行とビルドに使うツールチェーンを先に一覧にします。1.24以前から一気に上げる場合も、次章の挙動の変化はそのまま当てはまります。社内で棚卸しと更新を進める手が足りないときは、[システムマイグレーション・リプレイス](/service/system/migration/)の支援もご相談いただけます。

## 1.24から上げると挙動が変わる箇所

Go 1.25のリリースノートは「ほぼすべてのGoプログラムはこれまでどおりコンパイル・実行できる」としています。ただし、次の5点は出力や動作が変わります。どれもリリースノートでは別々の節に書かれているため、移行の確認項目として1か所にまとめます。

### nilチェック遅延バグの修正でpanicするコード

Go 1.21で入ったコンパイラのバグにより、1.21〜1.24ではnilポインタの検査が後ろへずれることがありました。リリースノートに載っている次のコードは、ファイルが無いので`f`はnilですが、1.24では何事もなく終了します。

```
package main

import "os"

func main() {
	f, err := os.Open("nonExistentFile")
	name := f.Name()
	if err != nil {
		return
	}
	println(name)
}
```

同じコードを2つのツールチェーンで実行した結果です。`GOTOOLCHAIN`に版を指定すると、goコマンドがその版を取得して実行します（仕組みは[GOTOOLCHAINとは｜Go toolchainの自動切り替えとgo.modのtoolchain行](/tech/details/5635/)）。

```
$ GOTOOLCHAIN=go1.24.13 go run .
（何も出力されず終了コード0）

$ GOTOOLCHAIN=go1.25.14 go run .
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x3732665]

goroutine 1 [running]:
os.(*File).Name(...)
```

これは言語仕様どおりの挙動に戻す修正で、**go.modのgo行を1.24のままにしてgo1.25.14でビルドしても同じくpanicしました**。go行で旧挙動に戻すことはできません。対処は、エラーを返す呼び出しの直後に`err`を確かめる順序へ書き直すことです。[Go言語のエラーハンドリング実装ガイド](/tech/details/3895/)で扱っている、呼び出しの直後に`err`を判定する形にしておけば、この修正の影響は受けません。

### スライスのスタック割り当て拡大とunsafe.Pointerの誤用

1.25のコンパイラは、要素数が変数の`make`でも、スライスが関数の外へ逃げなければ、小さいバッキング配列をスタックに置くようになりました。次の関数をインライン化させずにベンチマークすると、ヒープ割り当ての回数が変わります。

```
//go:noinline
func Sum(n int) int {
	buf := make([]int, n)
	for i := range buf {
		buf[i] = i
	}
	s := 0
	for _, v := range buf {
		s += v
	}
	return s
}
```

```
$ GOTOOLCHAIN=go1.24.13 go build -gcflags=-m .
./s.go:5:13: make([]int, n) escapes to heap
$ GOTOOLCHAIN=go1.25.14 go build -gcflags=-m .
./s.go:5:13: make([]int, n) does not escape

（ベンチマークのB/opとallocs/op）
              Sum(4)＝32バイト    Sum(64)＝512バイト
go1.24.13     32 B  / 1 alloc     512 B / 1 alloc
go1.25.14      0 B  / 0 alloc     512 B / 1 alloc
```

今回のdarwin/amd64環境ではintは1個8バイトで、int 4個（32バイト）の`Sum(4)`はヒープ割り当てが0回になり、512バイトの`Sum(64)`は従来どおり1回でした。go.modのgo行は1.24のままで、この変更はgo行に関係なくコンパイラ側で効きます。

リリースノートは、この変更が`unsafe.Pointer`の誤った使い方の影響を増幅しうるとし、例として[issue 73199](https://go.dev/issue/73199)を挙げています。1.25へ上げてからメモリ破壊のようなクラッシュが出たら、`-gcflags=all=-d=variablemakehash=n`で新しいスタック割り当てを止めて再現するかを確かめます。上のベンチマークにこのフラグを付けると、`Sum(4)`は32 B/op・1 allocs/opに戻りました。原因の割り当てを絞り込むときは、bisectツールに`-compile=variablemake`を渡します。

### go.modのgo行で切り替わる既定値（DefaultGODEBUG）

Goは互換性を保つため、挙動を変える修正の多くをGODEBUG設定で包み、go.modのgo行が古いモジュールでは旧挙動を既定にします。go行を`go 1.24`のままgo1.25.14でビルドしたバイナリを`go version -m`で見ると、次の設定が埋め込まれていました。

```
$ go version -m b125
...
	build	DefaultGODEBUG=containermaxprocs=0,decoratemappings=0,tlssha1=1,updatemaxprocs=0,x509sha256skid=0
```

go行を`go 1.25`にするとこの行は消え、1.25の新しい既定値が有効になります。各設定の意味は[GoのGODEBUG一覧](https://go.dev/doc/godebug)に載っています。

| 設定                | go 1.24行のとき     | go 1.25行のとき    |
| ----------------- | --------------- | -------------- |
| containermaxprocs | 0（cgroup上限を見ない） | 1（上限を見る）       |
| updatemaxprocs    | 0（更新しない）        | 1（定期的に更新）      |
| tlssha1           | 1（SHA-1署名を許可）   | 既定で拒否          |
| x509sha256skid    | 0（SHA-1で生成）     | SHA-256で生成     |
| decoratemappings  | 0（名前なし）         | Linuxでメモリ領域に名前 |

つまり、**ツールチェーンだけを1.25に上げても、コンテナ対応のGOMAXPROCSは動きません**。逆に、go行を1.25へ上げた時点でTLS 1.2のSHA-1署名（[RFC 9155](https://datatracker.ietf.org/doc/html/rfc9155)）が拒否されるため、古い機器と通信するクライアントはこのタイミングで接続に失敗する可能性があります。その場合は`GODEBUG=tlssha1=1`で一時的に戻せます。

### recoverしたpanicを投げ直したときの表示

recoverしたpanicを同じ値で投げ直すと、1.24まではメッセージが2行に重複して出ていました。1.25では1行にまとまります。

```
$ GOTOOLCHAIN=go1.24.13 go run .
panic: PANIC [recovered]
	panic: PANIC

$ GOTOOLCHAIN=go1.25.14 go run .
panic: PANIC [recovered, repanicked]
```

ログ監視で`[recovered]`の直後の行をパターンにしている場合は、1.25で一致しなくなります。

### macOS 12未満の切り捨てとwindows/armの最終版

Go 1.25の実行にはmacOS 12 Monterey以降が必要です。32ビットのwindows/arm（`GOOS=windows GOARCH=arm`）は1.25が最後の収録で、1.26で削除されました。さらに1.26は「macOS 12で動く最後のリリース」とされ、1.27ではmacOS 13 Ventura以降が必要です（[Go 1.27のリリースノート](https://go.dev/doc/go1.27)）。古いmacOSのビルド機を残している場合、1.25から先は版ごとに足切りが進む点に注意してください。

## コンテナ対応GOMAXPROCS：Kubernetesのlimitsによる既定値の変更

1.24までのGOMAXPROCSは、起動時の論理CPU数（`runtime.NumCPU`）が既定でした。Kubernetesで`limits.cpu`を2に絞っても、ノードが64コアならGOMAXPROCSは64になり、CPUクォータを使い切ってスロットリングされる原因になっていました。

1.25（go行が1.25以上）では、Linuxでプロセスが属するcgroupのCPU帯域上限を読み、論理CPU数より小さければそちらを既定にします。go1.25.14の[src/runtime/cgroup\_linux.go](https://github.com/golang/go/blob/go1.25.14/src/runtime/cgroup%5Flinux.go)では、上限（quota÷period）の端数を切り上げ、2未満は2にしてから論理CPU数と比べています。

| ノードの論理CPU | limits.cpu | 1.24の既定 | 1.25の既定 |
| --------- | ---------- | ------- | ------- |
| 64        | 2          | 64      | 2       |
| 64        | 2.5        | 64      | 3       |
| 64        | 0.5        | 64      | 2       |
| 64        | 指定なし       | 64      | 64      |

表は、プロセスが64個の論理CPUすべてを利用でき、GOMAXPROCSやGODEBUGを上書きしていない場合の計算値です。CPU affinityで利用可能CPUが制限される場合は、その数も既定値に影響します。**見るのはCPUの上限（limits）だけで、requestsは考慮しません**（リリースノートに明記）。requestsだけを設定しているPodでは何も変わりません。[Kubernetes](/tech/details/2928/)でlimitsを付けていない構成なら、1.25へ上げてもGOMAXPROCSは従来どおりです。

もう1つの変更として、ランタイムは論理CPU数やCPU affinityの変化を定期的に確認し、GOMAXPROCSを更新します。LinuxではcgroupのCPU帯域上限の変化も反映します。環境変数`GOMAXPROCS`や`runtime.GOMAXPROCS`で手動設定するとどちらも無効になり、個別に止めるには`GODEBUG=containermaxprocs=0`と`updatemaxprocs=0`を使います。手動設定を解除して新しい既定値に戻すための`runtime.SetDefaultGOMAXPROCS`も追加されました。GOMAXPROCSがスケジューラのPの数を決める仕組みは[GMPモデルの解説](/tech/details/4542/)で説明しています。

## testing/synctestとテスト関連の追加

### synctest.Testで時間を仮想化

`testing/synctest`は1.24で`GOEXPERIMENT=synctest`付きの実験機能として入り、1.25で正式機能になりました。`synctest.Test`の中（バブル）では`time`パッケージが偽の時計で動き、バブル内の全ゴルーチンがdurably blocked（バブル内部の処理だけで解除される待機状態）になると、次のタイマー時刻まで時計が進みます。ネットワークI/OやMutexのロック待ちは、この条件に含まれません。1時間のタイムアウトを持つ[context](/tech/details/3757/)の期限切れを確かめるテストは次のように書けます。

```
func TestTimeout(t *testing.T) {
	synctest.Test(t, func(t *testing.T) {
		start := time.Now()
		ctx, cancel := context.WithTimeout(t.Context(), time.Hour)
		defer cancel()
		time.Sleep(59 * time.Minute)
		synctest.Wait()
		if err := ctx.Err(); err != nil {
			t.Fatalf("59分で期限切れ: %v", err)
		}
		time.Sleep(time.Minute)
		synctest.Wait()
		if ctx.Err() != context.DeadlineExceeded {
			t.Fatalf("60分で期限切れにならない: %v", ctx.Err())
		}
		t.Logf("仮想時計の経過: %v", time.Since(start))
	})
}
```

```
$ go test -v -run Timeout .
    sync_test.go:25: 仮想時計の経過: 1h0m0s
--- PASS: TestTimeout (0.00s)
```

テスト内の時計は1時間進み、実時間は0.00秒です。1.24の実験版で使っていた`synctest.Run`は、1.25では`GOEXPERIMENT=synctest`を付けたときだけ残っています。付けずにビルドすると`undefined: synctest.Run`になり、go1.26.5では`GOEXPERIMENT=synctest`自体が`unknown GOEXPERIMENT synctest`で拒否されました。1.24の実験版で書いたテストは、1.25へ上げる時点で`synctest.Test`へ書き換えるのが手戻りの少ない順序です。

### T.Attr・Outputと-jsonのattrアクション

`T.Attr`・`B.Attr`・`F.Attr`は、テストにキーと値の属性を付けてログへ出力します。チケット番号やテスト対象の環境名など、テスト名だけでは分からない情報を結果に残すときに使います。

```
func TestAttr(t *testing.T) {
	t.Attr("issue", "GH-1234")
	fmt.Fprintln(t.Output(), "Outputへの書き込み")
	t.Log("Logへの書き込み")
}
```

```
$ go test -v -run Attr .
=== RUN   TestAttr
=== ATTR  TestAttr issue GH-1234
    Outputへの書き込み
    attr_test.go:11: Logへの書き込み

$ go test -json -run Attr . | grep attr
{"Action":"attr","Package":"feat","Test":"TestAttr","Key":"issue","Value":"GH-1234"}
```

`-json`では`"Action":"attr"`の独立した行になるため、CIのパーサーは`Key`と`Value`を直接読めます（出力の`Time`は省略）。新しい`Output`メソッドは`t.Log`と同じ字下げで書き込みますが、ファイル名と行番号は付きません。このほか、並列テストの実行中に`testing.AllocsPerRun`を呼ぶとpanicするようになりました。他のテストの割り当てが混ざって結果が不安定になるのを防ぐためです。

## sync.WaitGroup.Goとgo vetの新しい検査

`sync.WaitGroup.Go`は、`wg.Add(1)`・`go func()`・`defer wg.Done()`の3行を1回の呼び出しにまとめます。渡す関数はpanicしてはならず、WaitGroupが空の場合はWaitより先にGoを呼ぶ必要があります。

```
var wg sync.WaitGroup
var n atomic.Int64
for i := range 100 {
	wg.Go(func() { n.Add(int64(i)) })
}
wg.Wait()
```

あわせてgo vetに2つのアナライザーが入りました。`waitgroup`はゴルーチンの中で`wg.Add`を呼ぶ誤り（`Wait`が先に戻る競合の原因）を、`hostport`はIPv6で動かない`fmt.Sprintf("%s:%d", host, port)`形式のアドレス組み立てを報告します。

```
$ go vet ./vetwg
vetwg/main.go:12:10: WaitGroup.Add called from inside new goroutine

$ go vet ./vethp
vethp/main.go:10:43: address format "%s:%d" does not work with IPv6
```

`hostport`の指摘には`net.JoinHostPort`で直します。注意したいのは、go行が`go 1.24`のモジュールで`wg.Go`を使った場合です。go1.25.14では`go build`は通りましたが、`go vet`が`sync.Go requires go1.25 or later (module is go1.24)`を報告しました。新しいAPIを使うならgo行も1.25へ上げてください。排他制御全般の使い分けは[sync.MutexとRWMutexの違いと使い分け](/tech/details/5549/)、ゴルーチンの基本は[ゴルーチン（Goroutine）とは](/tech/details/4632/)で扱っています。

## 実験機能のその後：Green Tea GCとencoding/json/v2

1.25で`GOEXPERIMENT`として入った2つの機能は、その後の版で既定・正式に変わっています。1.25のまま試す場合と、1.26以降で使う場合では切り替え方が逆になる点に注意してください。

| 機能               | Go 1.25        | Go 1.26              | Go 1.27          |
| ---------------- | -------------- | -------------------- | ---------------- |
| Green Tea GC     | greenteagcで有効化 | 既定（nogreenteagcで無効化） | 既定               |
| encoding/json/v2 | jsonv2で有効化     | 実験のまま                | 正式（nojsonv2で旧実装） |
| synctest旧API     | synctestで残存    | GOEXPERIMENT自体が不明    | 同左               |

### Green Tea GCの処理負荷削減と後続版での既定化

小さいオブジェクトのマークとスキャンを、メモリの局所性とCPUのスケーラビリティを高める設計に変えたGCです。1.25のリリースノートは、GCを多用する実プログラムでGCのオーバーヘッドが10〜40%減ると見込んでいます。1.26で既定になり、`GOEXPERIMENT=nogreenteagc`で無効にできます。[Go 1.26のリリースノート](https://go.dev/doc/go1.26)は「この無効化設定は1.27で削除される見込み」としていましたが、go1.27.3でも`GOEXPERIMENT=nogreenteagc`付きのビルドは通り、`go version -m`には`GOEXPERIMENT=nogreenteagc`が記録されました（2026年10月31日確認）。1.25で本番に試験導入するより、既定になった1.26以降へ上げて評価するほうが手戻りがありません。

### encoding/json/v2の入出力の違いとGo 1.27での正式化

1.25では`GOEXPERIMENT=jsonv2`を付けたときだけ`encoding/json/v2`と`encoding/json/jsontext`が使えます。付けずにimportすると`build constraints exclude all Go files`でビルドできません。v1とv2で同じ入力を処理すると、次の違いが出ました（go1.25.14、go1.27.1とも同じ結果）。

| 入力・操作             | v1（encoding/json） | v2                           |
| ----------------- | ----------------- | ---------------------------- |
| nilスライスを出力        | `"tags":null`     | `"tags":[]`                  |
| `{"NAME":"b"}`を読む | Nameに`b`が入る       | 空のまま                         |
| 重複キーを読む           | エラーなし             | duplicate object member name |

v2はキー名の大文字小文字を区別し、重複キーをエラーにします。外部APIの大文字キーをv1の緩い照合に頼って読んでいるコードは、v2へ移すと値が空になります。1.25の`jsonv2`実験ではv1の`encoding/json`も新実装の上で動きますが、リリースノートは「エンコード・デコードの結果は変わらず、エラー文言だけが変わりうる」としています。v2は1.27で正式版になったため、v2のAPIで書き直すなら1.27以降を前提にするのが筋です。

## ツールチェーンの追加：go.mod ignore・DWARF5・ASan

### go.modのignoreによるパッケージ探索からの除外

go.modに`ignore`を書くと、`./...`や`all`のパターン照合からそのディレクトリを外せます。フロントエンドと同居するリポジトリで、`node_modules`内の`.go`ファイルがビルドを壊す問題への対処です。

```
module ign

go 1.25

ignore ./node_modules
```

```
$ go build ./...        # ignore なし
node_modules/x/bad.go:3:1: syntax error: non-declaration statement outside function body

$ go build ./...        # ignore あり
（成功・go list ./... は ign のみ）

$ GOTOOLCHAIN=go1.24.13 go build ./...
go: errors parsing go.mod:
go.mod:5: unknown directive: ignore
```

無視したディレクトリもモジュールのzipには含まれます。**go1.24.13はignore行のあるgo.modを読めずに止まる**ため、チームやCIに1.24以前のツールチェーンが残っている間は書けません。

### DWARF 5によるデバッグ情報のサイズ削減

1.25のコンパイラとリンカはデバッグ情報をDWARF 5で出力します。net/httpで1ハンドラだけのサーバーをlinux/amd64向けにビルドし、`.debug_`セクションの合計を比べました。

| ビルド                | .debug\_合計   | ファイルサイズ      |
| ------------------ | ------------ | ------------ |
| go1.24.13          | 7,730,472バイト | 8,193,887バイト |
| go1.25.14          | 4,739,267バイト | 8,102,359バイト |
| go1.25.14 nodwarf5 | 7,895,278バイト | 8,310,588バイト |

ELFの各デバッグセクションの展開後サイズを合計すると約39%減りましたが、圧縮されたデバッグ情報を含むファイル全体では約1%の差にとどまります。デバッガやプロファイラがDWARF 5を読めない場合は`GOEXPERIMENT=nodwarf5`で旧形式に戻せますが、リリースノートはこの退避手段を将来削除しうるとしています。

### go build -asanのリーク検出と小さなgoコマンド変更

`go build -asan`は、プログラム終了時のメモリリーク検出が既定になりました。Cで確保され、CからもGoからも参照されずに解放されていないメモリがあるとエラーを報告します。cgoのリークを許容して既存のCIを通す場合は、実行時に`ASAN_OPTIONS=detect_leaks=0`を設定します。ASan自体の読み方は[Segmentation faultの原因と調べ方](/tech/details/7982/)で説明しています。そのほかのgoコマンドの変更は次のとおりです。

- `go doc -http`：指定した対象のドキュメントサーバーを起動し、ブラウザで開く
- `go version -m -json`：バイナリに埋め込まれたビルド情報をJSONで出力
- `work`パターン：ワークスペース内のモジュールのパッケージすべてに一致
- go.modのgo行を更新しても`toolchain`行を自動で足さなくなった
- ビルドやテストで使わないツールは同梱せず、`go tool`が必要時にビルド

## 標準ライブラリの注目変更

### net/http.CrossOriginProtectionによるCSRF対策

`http.CrossOriginProtection`は、トークンやCookieを使わずにCSRFを防ぐハンドラーです。ブラウザが付ける`Sec-Fetch-Site`ヘッダーと`Origin`ヘッダーを見て、安全でないメソッドのクロスオリジン要求を拒否します。`httptest`で要求を組み立てて確かめた結果です。

| 要求                                    | 応答  |
| ------------------------------------- | --- |
| POST・Sec-Fetch-Site: cross-site       | 403 |
| POST・Sec-Fetch-Site: same-origin      | 200 |
| GET・Sec-Fetch-Site: cross-site        | 200 |
| POST・ヘッダーなし（curl等）                    | 200 |
| POST・Originのみ別ホスト                     | 403 |
| POST・cross-site＋AddTrustedOriginで登録済み | 200 |

ヘッダーを付けないcurlやサーバー間通信の要求は通ります。この設計では、ヘッダーのない要求を同一オリジンまたはブラウザ以外からの要求として扱います。ただし、常に許可されるGET・HEAD・OPTIONSでデータ更新などの状態変更を行わないことが前提です。逆にいえば、API認証の代わりにはなりません。外部の決済画面などからのPOSTを受ける場合は、`AddTrustedOrigin`でそのオリジンを登録します。

### runtime/trace.FlightRecorderによる直前の実行トレースの保存

実行トレースをメモリ上のリングバッファへ記録し続け、異常を検知した時点で直前の数秒分だけをファイルへ書き出す仕組みです。トレースを常時ファイルへ保存するI/Oを避けながら、まれな遅延の原因を追えます。ただし、実行中のイベント記録とメモリ保持のコストは発生します。

```
fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{
	MinAge:   5 * time.Second,
	MaxBytes: 4 << 20,
})
if err := fr.Start(); err != nil {
	log.Fatal(err)
}
defer fr.Stop()

// 遅い要求などを検知したら
f, err := os.Create("slow.trace")
if err != nil {
	log.Print(err)
	return
}
defer f.Close()
if _, err := fr.WriteTo(f); err != nil {
	log.Print(err)
}
```

`MinAge`は保持する期間の下限、`MaxBytes`は保持ウィンドウの容量上限の目安で、出力ファイルのサイズやメモリ使用量の厳密な上限を保証しません。両方を指定すると`MaxBytes`が優先されます（go doc runtime/trace.FlightRecorderConfig）。書き出したファイルは`go tool trace slow.trace`で開けます。

### os.Root・reflect・暗号ライブラリなどのAPI追加と性能変更

- `os.Root`：`ReadFile`・`WriteFile`・`MkdirAll`・`RemoveAll`・`Rename`など12メソッドを追加
- `reflect.TypeAssert`：`Value.Interface`を経由する型アサーションで生じる不要なメモリ割り当てを回避
- `log/slog`：`GroupAttrs`と`Record.Source`を追加
- `crypto/rsa`：鍵生成が3倍速く、`crypto/ecdsa`・`ed25519`はFIPS 140-3モードでの署名が4倍速く
- `unique`：不要になった値の回収が早まり、`Make`を多用したときのメモリ膨張が起きにくくなった

一方で、AVX2を持たないamd64ではSHA-1・SHA-256・SHA-512が遅くなりました。リリースノートは「2015年以降のサーバー向けプロセッサはほぼAVX2対応」としていますが、古い仮想CPU定義で動かしている環境では計測し直す価値があります。

## よくある質問

### Go 1.25はいつリリースされ、いつまでサポートされますか？

2025年8月12日にリリースされ、2026年8月19日のGo 1.27公開でサポートが終わりました。同じ日に出たgo1.25.14が最後のパッチで、2026年10月8日と19日に1.26系・1.27系へ出たセキュリティ修正は1.25系には出ていません。

### Go 1.25で言語仕様は変わりましたか？

プログラムに影響する言語の変更はありません。言語仕様書から「コア型（core type）」という概念を削除し、ジェネリクスの規則を個別の説明文に書き換えましたが、コンパイルできるコードの範囲は変わりません。

### ツールチェーンを1.25にすれば新機能は全部有効になりますか？

なりません。コンテナ対応のGOMAXPROCSやTLS 1.2のSHA-1署名拒否は、go.modのgo行が1.25以上のときに有効になります。一方、nilチェックの修正はgo行に関係なく、1.25のコンパイラでビルドした時点で効きます。

### Go 1.25で追加されたencoding/json/v2はそのまま使えますか？

1.25ではビルド時に`GOEXPERIMENT=jsonv2`が必要な実験機能です。正式版になったのはGo 1.27なので、本番で使うなら1.27以降を前提にしてください。

### 今Go 1.25を使っている場合、どの版へ上げるべきですか？

1.25はサポートが終わっているため、1.26か1.27へ上げます。2026年10月31日時点の最新パッチはgo1.27.3とgo1.26.10です。Green Tea GCが既定になる1.26、json/v2が正式版になる1.27と、版ごとに既定の挙動が変わります。最新の安定版と更新手順は[Go 1.27の新機能・変更点まとめ](/tech/details/10416/)で確認してください。

## 関連記事

- [Go 1.27の新機能・変更点まとめ｜Goの最新バージョンは1.27、確認・更新方法と移行の注意点](/tech/details/10416/)
- [govulncheckの使い方【v1.9.0】終了コード・ignore代替・Actions設定](/tech/details/3013/)
- [GOTOOLCHAINとは｜Go toolchainの自動切り替えとgo.modのtoolchain行【Go 1.27.3で実測】](/tech/details/5635/)
- [Go言語のエラーハンドリング実装ガイド｜errors.Is/As/AsTypeとpanic recoverの使い分け](/tech/details/3895/)
- [Go言語とは｜1.27系の導入からHTTP APIを動かすまでの実装入門](/tech/details/17483/)

---

出典: [Go 1.25の新機能と変更点｜サポート終了後の脆弱性と1.24から上げると変わる箇所を実測](<https://www.issoh.co.jp/tech/details/8421/>)（株式会社一創）
