Suppose you have a variable of the type of the struct mentioned below which you wanted to Unmarshal
.
type Building struct {
WindowCount int `json:"window_count"`
Doors int `json:"doors"`
}
In case the data is coming from an unreliable source, you can never be sure that the value you will receive will always have the correct format. You have to be cautious when working around data like this. If you are new in Go you might be wondering what will happen you Unmarshal
and incorrect value?
Compiler Loves Zero Values
If you unmarshal the code into a variable you will get the zero value for the fields WindowCount
, and Doors
. Which in some case can lead to bug because you might have different logic for missing case.
var b Building
json.Unmarshal([]byte(""), &b)
fmt.Printf("%+v\n", b)
// Output:
// {WindowCount:0 Doors:0}
Pointer To Rescue 🦸
If you have worked with pointers in languages like C, C++ you might have some opinion. You either like it or you hate it. Most people fall into the latter group. Working with pointers in Golang is fun because things are declarative comparatively.
If you set the field type to a pointer of that type it will be nil
in case the field is missing
type Building struct {
WindowCount *int `json:"window_count"`
Doors *int `json:"doors"`
}
Unmarshalling it has the following effect:
var b Building
json.Unmarshal([]byte(`{"window_count": 2}`), &b)
fmt.Printf("%+v\n", b)
// Output:
// {WindowCount:0xc000016170 Doors:<nil>}
The WindowCount
holds the pointer to an integer which holds the value 2. Whereas since doors
is missing from the JSON string it will set to nil
thanks to the zero value of pointers. You can now write your logic in case of the absence of that value.
Conclusion
Since the field of a struct is part of the contract of the struct it can't go missing entirely instead you need to handle it little differently. The most preferable way is to convert the type to a pointer of the same type and when in some case the value is missing it will be set to the zero value, which is nil
.
Top comments (1)
Nice trick Mohammad I didn't know that if we use pointers on types we get
nil
values, but be careful with this because you can have panic errors if you forgot to check if it's anil
orint
, what I would do is keep the type as it is and add a method to check if the field isnot zero
, like this:This way I don't need to check if the field is
nil
and can still perform arithmetic operations.