NullableなJSONフィールドのGoポインタ表現
GoのNullableなJSONフィールドにポインタ型(*string, *int)を使う理由とタイミングを学びます。nilとゼロ値のセマンティクスを解説。
Advanced Types
詳細な説明
NullableなJSONフィールドにポインタを使う
JSONは値として null をサポートしていますが、Goにはプリミティブのnull型がありません。解決策はポインタ型を使用することで、nil がJSON null を表します。
問題点
{ "name": "Alice", "age": null, "score": 0 }
通常の int フィールドでは、null と 0 の両方が 0 にアンマーシャリングされ、区別できなくなります。
解決策:ポインタ
type Player struct {
Name string `json:"name"`
Age *int `json:"age"`
Score *int `json:"score"`
}
これにより:
null→Ageはnil0→Scoreは値0のintを指す- キーが欠落 →
Ageはnil
ポインタフィールドの確認
if player.Age != nil {
fmt.Printf("Age: %d\n", *player.Age)
} else {
fmt.Println("Age: not provided")
}
ポインタを使うべき場面
以下の場合にポインタを使用します:
- APIがフィールドに
nullを送信し、それがゼロ値と異なる場合 - 「フィールドが存在しない」と「フィールドがゼロ」を区別する必要がある場合
- 変更されたフィールドのみ送信するPATCHリクエストボディの構築時
以下の場合はポインタを避けます:
- フィールドが常に存在し、非nullの場合
- ゼロ値がドメインで有効な値でない場合
- null安全性よりもシンプルさが重要な場合
omitemptyとの組み合わせ
Age *int `json:"age,omitempty"`
ポインタがnilの場合はフィールドを省略し、非nil(0 であっても)の場合は含めます。
パフォーマンスに関する注意
ポインタはフィールドごとに小さなヒープアロケーションを追加します。数百万のオブジェクトを処理する高スループットサービスでは、不必要なポインタの回避がパフォーマンスを向上させる場合があります。
ユースケース
データベースバックのAPIは、値のないカラムに対してnullを返すことが多いです。Go構造体でポインタフィールドを使用することで、年齢を0に設定したユーザーと設定していないユーザーを区別できます。