🤔

あれ?GORMでfalseや""が更新されない?になった時の対応

に公開

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秒でも短くできたら嬉しいです!

Discussion