GoでWebアプリを作っているときに、こんな状況に出会いました。
「あれ?Completedを
false
に戻したいのに、更新されてない…?」
結論から言うと、GORMのUpdates()は、ゼロ値(false, 0, "", nilなど)をスキップする仕様です。
同じようにハマった人に向けて、原因と解決法をまとめます!
🐛 ハマった状況
type Todo struct {
ID uint
Title string
Completed bool
}
input := Todo{
Completed: false,
}
db.Model(&todo).Updates(input) // ← Completedがfalseにならない!?
💡 なぜ起きるのか?
GORMの Updates(struct)
は、フィールドがゼロ値(default value)だった場合、自動的に更新対象から除外します。
つまり…
値 | 更新される? |
---|---|
"hello" |
✅ |
"" |
❌ |
true |
✅ |
false |
❌ |
1 |
✅ |
0 |
❌ |
✅ 解決策①:Selectを使って明示的に指定
db.Model(&todo).Select("Completed").Updates(input)
更新したいフィールドを明示すれば、ゼロ値も反映されます!
✅ 解決策②:mapで渡す
db.Model(&todo).Updates(map[string]interface{}{
"completed": false,
})
mapを使うとゼロ値でも無視されません。
📝 補足:GORMがスキップする「ゼロ値」とは?
Goにおけるゼロ値とは、初期化されていないときに代入される値のことです:
-
""
(空文字) -
0
(int) -
false
(bool) -
nil
(pointer, slice, mapなど)
GORMはこのゼロ値を「空欄」と見なして更新しない設計になっています。
🎯 まとめ
方法 | ゼロ値でも更新される? | 備考 |
---|---|---|
Updates(struct) |
❌ | デフォルトでは無視される |
Updates(struct).Select("field") |
✅ | 明示すればOK |
Updates(map[string]interface{}) |
✅ | mapならゼロ値もOK |
🚀 おわりに
個人開発や業務のCRUDでもよく使うUpdates()
ですが、
この「ゼロ値スキップ仕様」は知らないと確実にハマります😇
この記事が誰かのデバッグ時間を1秒でも短くできたら嬉しいです!