Test for nil values in nested stucts
One elegant way (in my opinion) of handling it is to add getters to structs that are used as pointers. This "technique" is also used by the generated Go code of protobuf, and it allows natural chaining of method calls without having to worry about runtime panic due to nil
pointers.
In your example the Bar
and Baz
structs are used as pointers, so arm them with getters. The focus is on adding methods with pointer receiver, and first it must be checked if the receiver is nil
. If so, return the zero value of the result type. If not, proceed to return the field of the struct:
func (b *Bar) GetBaz() *Baz {
if b == nil {
return nil
}
return b.Baz
}
func (b *Baz) GetBaz() string {
if b == nil {
return ""
}
return b.Baz
}
The good thing about methods with pointer receivers is that you may call them with nil
receivers. It does not cause a runtime panic until you try to refer to their fields, which we don't, that's why we first check if the receiver is nil
(ultimately, receivers act as normal parameters–and it's never an error to pass nil
as a pointer argument).
Having the above getters, use is simplified to this, and no runtime panic occurs in any of these examples:
fmt.Println(f3.Bar.GetBaz().GetBaz()) // naturally no panic
fmt.Println(f2.Bar.GetBaz().GetBaz()) // No panic
fmt.Println(f1.Bar.GetBaz().GetBaz()) // No panic
if baz := f2.Bar.GetBaz(); baz != nil {
fmt.Println(baz.GetBaz())
} else {
fmt.Println("something nil")
}
Try it on the Go Playground.
If you want to avoid 'reflect
' (reflection, as a "generic" way to test fields of any struct
, a bit as in "Get pointer to value using reflection" or in this gist: it is slower), the surest way would be to implement methods on Foo
in order to return the right value
func (foo *Foo) BarBaz() string {
if f2.Bar != nil && f2.Bar.Baz != nil {
return f2.Bar.Baz.Baz
} else {
fmt.Println("something nil")
return "" // for example
}
}
If there are a lot of such functions to write, maybe go 1.4 go generate
command can help generate most of them.