Today I found out that json.Marshal() weirdly return null for empty slice but make sense.

var slice []string
b, _ := json.Marshal(slice)
fmt.Println(string(b)) // print `null`

The workaround is to initiate empty slice using make() function.

var slice []string
slice = make([]string, 0)
b, _ := json.Marshal(slice)
fmt.Println(string(b)) // print `[]`

I thought make() will make fixed length slice and append() will trigger error, but it totally fine. That’s why in go they called it slice instead of array, the behavior is slightly different with fixed length array in another language.

var slice []string
slice = make([]string, 0)
fmt.Println(len(slice)) // print 0

slice = append(slice, "some-string")
fmt.Println(len(slice)) // print 1

b, _ := json.Marshal(slice)
fmt.Println(string(b)) // print `["some-string"]`

Thanks Dan Ott’s article for the insight