If I have a struct containing a nil
pointer of type A
, using reflect.DeepEqual
to check if that property is nil
will result in false
, which strikes me as odd behaviour.
type Container struct {
O *Obj
}
type Obj struct {
Message string
}
var c Container
eq := reflect.DeepEqual(c.O, nil)
fmt.Printf("O value: %v, is nil: %t", c.O, eq)
// Prints: "O value: <nil>, is nil: false"
Specifically, I am marshaling a JSON object into a struct, where I would like to test that a specific property is nil
when the corresponding JSON structure does not contain it. If reflect.DeepEqual
is not the way to go, how should I do this?
Everything you pass to reflect.DeepEqual()
is wrapped in an interface{}
value (if it's not already that):
func DeepEqual(x, y interface{}) bool
interface{}
values will be compared, where the first parameter value is not nil
, only the value wrapped in it.
An interface value is represented as a (type; value)
pair. The first value you pass to reflect.DeepEqual()
is a pair of (type; value)
being (*Obj, nil)
, and the 2nd value is nil
. They are not equal. The second value lacks type information.
If you compare it to a "typed" nil
, it will be true
:
reflect.DeepEqual(c.O, (*Obj)(nil)) // This is true
See this example:
fmt.Println("c.O:", c.O)
fmt.Println("c.O == nil:", c.O == nil)
fmt.Println("c.O deep equal to nil:", reflect.DeepEqual(c.O, nil))
fmt.Println("c.O deep equal to (*Obj)(nil):", reflect.DeepEqual(c.O, (*Obj)(nil)))
Output (try it on the Go Playground):
c.O: <nil>
c.O == nil: true
c.O deep equal to nil: false
c.O deep equal to (*Obj)(nil): true
See this question for a deeper insight:
Hiding nil values, understanding why golang fails here
If you want to check if the value wrapped inside a non-nil
interface is nil
, you can use reflection: reflect.Value.IsNil().
For more details see: Why interface type doesn't provide an "IsNil" method?