#状況
- 当たり前の機能だと思うかもしれないが少しハマった。
- golangの仕様で変数にnullを代入できない。例えば
int
型であれば初期化した時点で0の値が初期値として設定される。
var n int
println(n)
// 実行結果
0
- これでどういう問題が発生するかというと構造体でも初期化した時点で勝手に0が入ってしまいnull値を表現できない。
- すると
gin
のcontext
を使ってjson化した際にも、もちろんnull値が入らない。- jsonでnullが返せない!
- すると
package main
import (
"time"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
type NotNullJSON struct {
NotNullIntInit int `json:"not_null_id_init"`
NotNullIntNotInit int `json:"not_null_id_not_init"`
}
notNullJSON := new(NotNullJSON)
notNullJSON.NotNullIntInit = 1
c.JSON(200, nullableJSON)
})
r.Run()
}
// 実行結果(何も代入していないnot_null_id_not_initにも0が入っている)
{"not_null_id_init":1,"not_null_id_not_init":0}
#対処
- ポインタを指定すればいい
- ポインタは代入しなければnullが入っている
package main
import (
"time"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
type NullableJSON struct {
NullableIntInit *int `json:"nullable_id_init"`
NullableIntNotInit *int `json:"nullable_id_not_init"`
NotNullIntInit int `json:"not_null_id_init"`
NotNullIntNotInit int `json:"not_null_id_not_init"`
}
nullableJSON := new(NullableJSON)
nullableJSON.NotNullIntInit = 1
tmpInt := 1
// 代入方法に注意!
nullableJson.NullableIDInit = &tmpInt
c.JSON(200, nullableJSON)
})
r.Run()
}
// 実行結果(何も代入していないnullable_id_not_initにnullが入っている)
{"nullable_id_init":1,"nullable_id_not_init":null,"not_null_id_init":1,"not_null_id_not_init":0}
##おまけ・その他
- 実際は関数で計算した値などから代入することが多いと思うのでサンプルコードを置いておいた
- int以外の型でも同じ手法で対処できる。
- 使用していたのがginだったのでgin前提で書いたがechoなど多分他のフレームワークでも同じ考え方で対処できると思う。