英文:
Nil pointer to struct not deep equal to nil?
问题
如果我有一个包含类型为A
的nil
指针的结构体,在使用reflect.DeepEqual
检查该属性是否为nil
时,结果将为false
,这对我来说是奇怪的行为。
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)
// 输出: "O value: <nil>, is nil: false"
具体来说,我正在将一个JSON对象编组为一个结构体,我希望在相应的JSON结构不包含该属性时,测试特定属性是否为nil
。如果reflect.DeepEqual
不是正确的方法,我应该如何做到这一点?
英文:
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.
<!-- language: lang-go -->
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?
答案1
得分: 3
你传递给reflect.DeepEqual()
的所有内容都被包装在一个interface{}
值中(如果它还不是这样的话):
func DeepEqual(x, y interface{}) bool
将比较interface{}
值,其中第一个参数值不是nil
,只有包装在其中的值。
接口值表示为(type; value)
对。你传递给reflect.DeepEqual()
的第一个值是一个(type; value)
对,即(*Obj, nil)
,第二个值是nil
。它们不相等。第二个值缺少类型信息。
如果将其与“有类型的”nil
进行比较,结果将为true
:
reflect.DeepEqual(c.O, (*Obj)(nil)) // 这是true
看看这个例子:
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)))
输出结果(在Go Playground上尝试):
c.O: <nil>
c.O == nil: true
c.O deep equal to nil: false
c.O deep equal to (*Obj)(nil): true
参考这个问题以深入了解:
如果你想检查非nil
接口内部包装的值是否为nil
,可以使用反射:reflect.Value.IsNil()。
更多详情请参阅:https://stackoverflow.com/questions/43895862/why-interface-type-doesnt-provide-an-isnil-method/43896204#43896204
英文:
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:
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: https://stackoverflow.com/questions/43895862/why-interface-type-doesnt-provide-an-isnil-method/43896204#43896204
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论