Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
encoding/json/v2のUnmarshalはこう変わった:内部実装で見る設計改善
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Hiroki Kurasawa
February 21, 2026
Programming
0
460
encoding/json/v2のUnmarshalはこう変わった:内部実装で見る設計改善
Go Conference mini in Sendai 2026 のLT枠「encoding/json/v2のUnmarshalはこう変わった:内部実装で見る設計改善」で発表した登壇資料です。
Hiroki Kurasawa
February 21, 2026
Tweet
Share
More Decks by Hiroki Kurasawa
See All by Hiroki Kurasawa
Go1.26 go fixをプロダクトに適用して困ったこと
kurakura0916
0
460
Other Decks in Programming
See All in Programming
テレメトリーシグナルが導くパフォーマンス最適化 / Performance Optimization Driven by Telemetry Signals
seike460
PRO
2
200
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
790
L’IA au service des devs : Anatomie d'un assistant de Code Review
toham
0
150
AIコードレビューの導入・運用と AI駆動開発における「AI4QA」の取り組みについて
hagevvashi
0
570
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
2
590
AIと共にエンジニアとPMの “二刀流”を実現する
naruogram
0
110
Reactive ❤️ Loom: A Forbidden Love Story
franz1981
2
200
Codex CLIのSubagentsによる並列API実装 / Parallel API Implementation with Codex CLI Subagents
takatty
2
720
20260320登壇資料
pharct
0
140
存在論的プログラミング: 時間と存在を記述する
koriym
5
580
安いハードウェアでVulkan
fadis
1
840
The free-lunch guide to idea circularity
hollycummins
0
390
Featured
See All Featured
How to Ace a Technical Interview
jacobian
281
24k
RailsConf 2023
tenderlove
30
1.4k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
200
SEO for Brand Visibility & Recognition
aleyda
0
4.4k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
800
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
170
Navigating Weather and Climate Data
rabernat
0
150
Building Applications with DynamoDB
mza
96
7k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
170
Leo the Paperboy
mayatellez
5
1.6k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9k
Why Our Code Smells
bkeepers
PRO
340
58k
Transcript
encoding/json/v2のUnmarshalはこう変わった ~内部実装で見る設計改善 ~ Go Conference mini in Sendai 2026 @kurasawah
1
⾃⼰紹介 • 倉澤 大樹(@kurasawah) ◦ 株式会社ZOZOで検索機能を開発しています ◦ GoとElasticsearchが好きです 2
このテーマを話そうと思ったきっかけ • encoding/json/v2はGo1.25で実験的に追加された • v2では「処理速度」「メモリ使用量」「アロケーション回数」 「エラー内容」が改善された • 「なぜ改善されたのか?」を内部設計から理解したくなった • 調べてみると、自分のコードにも活かせそう
3
今日話す4つの改善ポイント 1. パッケージ分離 2. エラーの原因特定 3. オブジェクトの再利用(sync.Pool) 4. 効率的なバッファ管理 4
v2のUnmarshal: 4つの改善ポイント 5 func Unmarshal(in []byte, out any, opts ...Options)
(err error) { dec := export.GetBufferedDecoder(in, opts...) defer export.PutBufferedDecoder(dec) xd := export.Decoder(dec) err = unmarshalDecode(dec, out, &xd.Struct, true) return err } コード 改善ポイント export オブジェクト パッケージ分離 err エラーの原因特定 Get/PutBufferedDecoder オブジェクトの再利用(sync.Pool) Decoder 構造体 効率的なバッファ管理 src/encoding/json/v2/arshal.go
改善点1: パッケージ分離 v1: encoding/json 1パッケージに全機能が混在 v2: jsontext(構文層)+ json(意味層)に分離 パッケージ 層
例 jsontext 構文層 { , "name" , : , "Alice" ... json 意味層 "Alice" → User.Name なぜ良いか • 責務が分かれ、変更の影響範囲が限定される • 構文層(jsontext)を単独で利用できる 6
{"name":"Alice","age":"thirty"} → User.Ageはint型なのでエラー v1: cannot unmarshal string into Go struct
field User.Age v2: cannot unmarshal JSON string into Go int within "/age" 改善点2: エラーの原因特定 なぜ原因特定が容易か • JSONPointerで「どこで」、JSONKindで「何型が」失敗したか分かる &SemanticError{ … JSONPointer: "/age" , // どこで JSONKind: '"', // JSON型(string) GoType: reflect.TypeOf(int(0)), // 期待した型 ... } src/encoding/json/v2/errors.go
• v1: 毎回ゼロ値初期化 → 呼び出しごとにメモリ確保 • v2: GetBufferedDecoder PutBufferedDecoder でプール管理
なぜ良いか : 高頻度呼び出し時のアロケーションとGCへの負担を削減 改善点3: オブジェクトの再利用 (sync.Pool) 1回目: Unmarshal({"name":"Alice",...}) ↓ Decoder取得 ↓ 処理 ↓ Poolへ戻す 2回目: Unmarshal({"name":"Bob",...}) ↓ 同じDecoder再利用 8
なぜ良いか : buf[prevStart:prevEnd] でコピーなしに前回値へアクセス可能 例: {"name":"Alice","age":30} を "Alice" まで読んだ時 →
buf[prevStart:prevEnd] = "Alice" decodeBuffer — 1つの []byte を論理的に4分割 改善点4: 効率的なバッファ管理 9 type decodeBuffer struct { … buf []byte // 入力全体を保持するバッファ prevStart int // 前回読んだ値の開始位置 prevEnd int // 前回読んだ値の終了位置 rd io.Reader // 入力元(ストリーミング対応) } src/encoding/json/jsontext/decode.go
まとめ • パッケージ分離 : jsontext + jsonによる責務の分離 • エラーの原因特定 :
SemanticErrorによる構造化エラー • オブジェクトの再利用 : sync.Poolによるアロケーション削減 • 効率的なバッファ管理 : decodeBufferによるコピーなしアクセス 10