指向struct的nil指针不深等于nil吗?

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?