結論:omitemptyは便利だが罠がある omitemptyタグは空値を省略できて便利だが、falseや0が保存できなくなる罠がある。
特にboolean型で**「false」と「未設定」を区別したい場合は要注意**だ。
omitemptyとは 空値の場合にフィールドを省略するタグ。JSON/Firestoreへの保存時にデータサイズを削減できる。
type User struct { Name string `json:"name"` Email string `json:"email,omitempty"` // 空なら省略 } ⚠️ 最大の罠:「空」とみなされる値 以下の値は「空」として扱われ、omitempty付きフィールドから消える:
型 空とみなされる値 保存できない値の例 真偽値 false ❌ falseが保存不可 数値 0 ❌ 0が保存不可 文字列 "" ❌ 空文字列が保存不可 スライス/マップ nil または長さ0 ❌ 空配列が保存不可 ポインタ nil - 時刻 time.Timeのゼロ値 - 実例:boolean型の罠 問題のあるコード type Config struct { EnableFeature bool `firestore:"enableFeature,omitempty"` } config := Config{EnableFeature: false} // ❌ Firestoreに保存されない! // "enableFeature"フィールド自体が消える これでは「false」と「未設定」が区別できない。
解決策:ポインタ型を使う type Config struct { EnableFeature *bool `firestore:"enableFeature,omitempty"` } // パターン1: 未設定 config := Config{EnableFeature: nil} // → フィールド省略(未設定として扱える) // パターン2: 明示的にfalse falseValue := false config := Config{EnableFeature: &falseValue} // → ✅ falseとして保存される // パターン3: true trueValue := true config := Config{EnableFeature: &trueValue} // → ✅ trueとして保存される 動作比較 omitemptyあり type User struct { Name string `json:"name"` Age int `json:"age,omitempty"` Active bool `json:"active,omitempty"` } user := User{Name: "Alice", Age: 0, Active: false} // JSON: {"name":"Alice"} // ❌ Age=0 と Active=false は消える omitemptyなし user := User{Name: "Alice", Age: 0, Active: false} // JSON: {"name":"Alice","age":0,"active":false} // ✅ 0 と false もちゃんと保存される Firestore/JSONでの使い分け データ削減を優先する場合 Email string `json:"email,omitempty"` // 未入力のメールアドレスは保存しなくていい 値の区別が必要な場合 // boolean型: falseと未設定を区別したい IsAdmin *bool `firestore:"isAdmin,omitempty"` // 数値型: 0と未設定を区別したい Score *int `firestore:"score,omitempty"` まとめ omitemptyは空値を省略してデータサイズを削減できる false、0、空文字列は「空」扱いで消える(最大の罠) 値の区別が必要ならポインタ型を使う JSON/Firestoreどちらでも同じ仕組みで動作 Some illustrations on this site, including the Go Gopher, are by Renée French and licensed under CC BY 4....