はじめに
普段、バックエンドの実装はGoで書いております。 2025年8月にv1.25がリリースされましたが、なかなかキャッチアップする機会がなかったので今回キャッチアップしようと思います。
既に色々記事は出回っていますが、個人の理解を深めるために記事を書いております。
リリースノート
コンパイラーやランタイム環境、Linter部分は正直ちょっと難しすぎる💦💦💦ので、ChatGPTにサマリーを出してもらおうと思います。今回はその中から自分が気になった部分だけに焦点を当て記事を書いていきます!
ChatGPTの解説サマリー
Go 1.25 リリースノート超まとめ
(公式 https://tip.golang.org/doc/go1.25 の流れに沿った説明)
1. はじめに
Go 1.25 は 1.24 から約 6 ヶ月後のリリース。
言語の大きな変更はなく、
ツールチェーン / ランタイム / 標準ライブラリの改善中心。
既存コードはほぼそのまま動くことを前提としている。
2. 言語仕様
言語仕様そのものの変更はなし。
ただし内部的な整理として core types(コア型)という概念が削除された。
一般的な Go 開発者には影響ほぼなし。
3. ツール(go コマンド・ビルド)
主な改善
-
go build -asan
C 側で解放漏れしたメモリを終了時に検出できるように。 - 事前ビルドされていたツールが削減され、
go tool実行に応じてビルドされる方式へ変更。 -
go.modに ignore ディレクティブ追加。
→ 指定ディレクトリを./...などのパターン検索から除外可能。 -
go doc -http
→ ローカルでドキュメントサーバを立てブラウザで閲覧可能。 -
go version -m -json <binary>
→ バイナリに含まれる BuildInfo を JSON で出力。 - モジュールパス解決強化
→<meta name="go-import" content="path vcs repo subdir">のように
リポジトリ内のサブディレクトリをモジュールルート扱いにできる。
go vet の強化
-
waitgroupanalyzer:WaitGroup.Add の誤使用検出。 -
hostportanalyzer:IPv6 非対応のアドレス生成を検出。
4. ランタイム
cgroup / コンテナ対応強化
- CPU クォータ(帯域制限)を考慮して GOMAXPROCS を自動調整。
- 実行中に CPU 制限が変更された場合も自動で更新。
GC(ガーベジコレクタ)
- 実験的新 GC “Green Tea GC” が導入。
→ 小さなオブジェクト大量処理で GC 負荷が大幅削減(10〜40%)。
メモリ可視性向上
- Linux 上で匿名 VMA に
[anon: Go: heap]のような用途名が付与。
panic 出力改善
- recover 後などの二重 panic 出力が簡潔に。
5. コンパイラ / リンカ
- デフォルトのデバッグ情報が DWARF v5 に。
→ デバッグ情報が小さくなりリンクが高速化。 - スライスの裏側の配列が スタックに割り当てられるケース増加。
→ パフォーマンス向上。ただし unsafe 使用コードは要注意。 - リンカに
-funcalign=N追加(関数のアライメント調整)。
6. 標準ライブラリ
大きなポイント
-
testing/synctestが 安定版に昇格。
→ 並行処理のテストがしやすい専用ツールが正式に。 - 実験版
encoding/json/v2が追加(GOEXPERIMENT=jsonv2)。
→ 高速で、より堅牢な JSON 実装。
その他
-
archive/tar.Writer.AddFSがシンボリックリンクをサポート。 - 暗号パッケージ(ECDSA/RSA/ED25519)で低レベル API・最適化。
-
net/httpに Cross-Origin Protection(CSRF軽減)機能。
7. プラットフォーム
- macOS は 12 Monterey 以降が必須。
- Windows の 32bit ARM (
GOARCH=arm) は 1.25 が最終対応。
→ 1.26 で削除予定。 -
GOAMD64=v3で FMA(fused multiply-add)を使用可能。
8. 移行ガイド(互換性)
- 基本は 既存コードそのまま動作。
- 気をつける点:
-
unsafe.Pointerを使うコードはスタック割当増加で影響の可能性。 - 実験機能(jsonv2 / greenteagc)は本番投入前に検証が必要。
- 古い macOS / Windows ARM32 は非対応へ移行。
-
気になった箇所をピックアップして説明していきます!
実際に手を動かしながら理解を深めていきましょう!!
事前準備
~/develop/go_version_125_jikkenn (main)$ tree
.
├── app
│ ├── go.mod
│ ├── ignoreme
│ │ └── ignore.go
│ └── main.go
├── docker-compose.yml
├── go1.24
│ └── Dockerfile
└── go1.25
└── Dockerfile
4 directories, 6 files
version: "3.9"
services:
go124:
build:
context: ./go1.24
volumes:
- ./app:/app
working_dir: /app
container_name: go124
go125:
build:
context: ./go1.25
volumes:
- ./app:/app
working_dir: /app
container_name: go125
FROM golang:1.24
WORKDIR /app
FROM golang:1.25
WORKDIR /app
module example.com/demo
go 1.25
ignore ignoreme
package main
import "fmt"
func main() {
fmt.Println("hello")
}
→大体の準備が整いました!
1. go.mod の ignore ディレクティブ
特定ディレクトリを Go が “存在しないもの” と扱ってくれる。
実際に手を動かしながら学んでいこうと思います!!DockerでGoのv1.24とv1.25環境を用意し対象実験をします。
package ignoreme
func Bad() {
undefined + symbol // コンパイルエラー
}
~/develop/go_version_125_jikkenn (main)$ docker compose build
~/develop/go_version_125_jikkenn (main)$ docker compose run --rm go124 bash
[+] Running 1/0
⠿ Network go_version_125_jikkenn_default Created 0.0s
root@809fcdf079ff:/app# go build ./...
go: go.mod requires go >= 1.25 (running go 1.24.10; GOTOOLCHAIN=local)
root@809fcdf079ff:/app# vi go.mod
bash: vi: command not found
→これだと怒られたので、v1.24用にgo.modを変更します!
→Docker環境を再ビルド
~/develop/go_version_125_jikkenn (main)$ docker compose run --rm go124 bash
root@c10aead0c508:/app# go build ./...
# example.com/demo/ignoreme
ignoreme/ignore.go:4:2: undefined: undefined
ignoreme/ignore.go:4:14: undefined: symbol
→確かに怒られました!!次はGo1.25にしてみましょう!
~/develop/go_version_125_jikkenn (main)$ docker compose run --rm go125 bash
root@b5f47c88c56e:/app# go build ./...
→お、確かにエラーでているのに無視してビルドが通りますね!
これでTypeScriptやShell、Doc等は明示的にディレクトリ単位で無視できるということか!なかなか便利かもですね!!
2. testing/synctestを体験する
これは Go 1.25 で「実験」→「正式」になった並行処理テスト用の仕組みで、
• goroutine の動きが安定する
• タイマー系の flaky テストが減る
• “時間をコントロールできるテスト” が書ける
では、実際に動かしていきましょう!!
synctest で何が嬉しい?
- goroutine の実行順が揺れない
- 並行処理の “たまに落ちる” テストが減る
- deadlock を自動検出してくれる
最小のサンプル(Go 1.25 で動く)
package main
import (
"sync"
"testing"
"testing/synctest"
)
func TestMutex(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
var mu sync.Mutex
counter := 0
go func() {
mu.Lock()
counter++
mu.Unlock()
}()
// goroutine の完了を確実に待つ(Sleep や WaitGroup は不要)
synctest.Wait()
if counter != 1 {
t.Fatalf("counter = %d, expected 1", counter)
}
})
}
3. 新しいJSON実装「encoding/json/v2」
Go 1.25 では、新しい JSON 実装 encoding/json/v2 が “実験的” に追加されました。
(正式版ではありません。GOEXPERIMENT=jsonv2 が必要です)
何が良くなるの?
- 従来の
encoding/jsonより高速 - エラーがより正確 & 型変換の挙動が改善
- 大量 JSON の API サーバで性能向上が期待できる
package main
import (
jsonv2 "encoding/json/v2"
"fmt"
)
type User struct {
Name string
Age int
}
func main() {
data := []byte(`{"Name":"Kawamura","Age":36}`)
var u User
if err := jsonv2.Unmarshal(data, &u); err != nil {
panic(err)
}
fmt.Println(u.Name, u.Age)
}
~/develop/go_version_125_jikkenn (main)$ docker compose run --rm go125 bash
root@712b286c28ed:/app# GOEXPERIMENT=jsonv2 go run main.go
Kawamura 36
→動きましたね!ただ、いまいち良さがわからないですね。
堅牢になってパフォーマンスが上がったみたいです!実験してみましょう!!
package main
import (
stdjson "encoding/json"
jsonv2 "encoding/json/v2"
"testing"
)
type BenchUser struct {
Name string
Age int
Email string
Active bool
Tags []string
Scores []float64
}
var benchJSON = []byte(`{
"Name": "Kawamura Koji",
"Age": 36,
"Email": "koji@example.com",
"Active": true,
"Tags": ["go", "backend", "hitotsu", "json"],
"Scores": [1.1, 2.2, 3.3, 4.4, 5.5]
}`)
// 旧 encoding/json のベンチ
func BenchmarkStdJSONUnmarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
var u BenchUser
if err := stdjson.Unmarshal(benchJSON, &u); err != nil {
b.Fatal(err)
}
}
}
// json/v2 のベンチ
func BenchmarkJSONv2Unmarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
var u BenchUser
if err := jsonv2.Unmarshal(benchJSON, &u); err != nil {
b.Fatal(err)
}
}
}
~/develop/go_version_125_jikkenn (main)$ docker compose run --rm go125 bash
root@e558a53ecebe:/app# GOEXPERIMENT=jsonv2 go test -bench=. -benchmem
goos: linux
goarch: arm64
pkg: example.com/demo
BenchmarkStdJSONUnmarshal-6 824684 1233 ns/op 328 B/op 8 allocs/op
BenchmarkJSONv2Unmarshal-6 1000000 1013 ns/op 328 B/op 8 allocs/op
PASS
ok example.com/demo 2.068s
(1233 - 1013) / 1233 = 約 17.8% 高速
→約18%改善されたようですね!!置き換えるだけで18%上がるのはいいですね!!
安定版になったら置き換えようと思います!!

