Golang empty []byte serialized to nil not []

Slices and arrays are differnet in golang serialization details. An uninitialized slice will be marshalled to JSON "null" value instead of "[]".

Uninitialized Slice

Given a simple RESTful listing handler, the uninitialized slice could still be appended with query result iteration by overwriting the slice variable.

var s []string
for _, item := range someResult {
s = append(s, item)
}
res, _ := json.Marshal(struct{ Items []string }{Items: s})
fmt.Printf("res = %s\n", res)

However, when the query result is empty, the uninitialized slice will be encoded to null. In this case, if someResult is empty, the output will be res = {"Items":null}. It's sometimes unfriendly to downstream APIs - usually the listing request expects an empty JSON array but not a null result.

Initialized Slice

In the above case, the slice shall be initialized first. For an empty start value, it could be initialized to zero sized and the re-slice procedure will automatically extend it in go-runtime doubling algorithm.

var s []string = make([]string, 0) // or s:= []string{}
for _, item := range someResult {
s = append(s, item)
}
res, _ := json.Marshal(struct{ Items []string }{Items: s})
fmt.Printf("res = %s\n", res)

If the query result is empty, it will still print res = {"Items":[]}. Same tips on map, an uninitialized reference type will be marshalled to "null" not an empty value.

Change Log

Oct, 2021: Initial post draft.