奇怪的零/非零行为

时间:2015-10-26 01:09:17

标签: go

我的项目中有以下代码:

        mod := srt.PrimaryModule()
        if mod != nil {
            mods[mod.Name()] = mod
        }

当它执行时,我得到:

PANIC: runtime error: invalid memory address or nil pointer dereference

堆栈就在第三行。 (是的,mod取消引用,地图mods仅在上面一行创建...)

那么,什么时候nil值不等于nil?为什么?

 srt.PrimaryModule() 

返回一个接口类型Module,其中定义的Name()方法返回string

在这种特殊情况下,srt是键入的StdReflectedType,这是一个函数PrimaryModule()返回类型Module的接口类型。 srt的实际实现是一个结构,它从其字段中返回未初始化的Module值。

此外,如果我这样做

reflect.ValueOf(mod)

结果是零反射。值。

来自反射包文档:

 ValueOf returns a new Value initialized to the concrete value stored in the interface i. ValueOf(nil) returns the zero Value

这似乎是正确的,除了上一行刚确定mod != nil。那是什么给出了什么?

我似乎无法在一个最小的例子中重现这一点 - 是否有任何明智的行为可能会导致这些行做到这一点 - 我不理解接口值和nil指针的重要事项吗?

1 个答案:

答案 0 :(得分:2)

如果界面中存储了任何具体值,则界面将不是nil。但是,存储在接口中的具体值可以是nil指针。

例如,fmt.Println(mod)输出,具体值是nil

if mod != nil {
    fmt.Println(mod)
    mods[mod.Name()] = mod
}

srt.PrimaryModule()是否会向nil返回mod指针?如果是,mod.Name()panic nil pointer dereference

参考文献:

The Go Programming Language SpecificationInterface types

Go Data Structures: Interfaces

Why is my nil error value not equal to nil?

此修订版代码的输出是什么?

mod := srt.PrimaryModule()
if mod != nil {
    fmt.Printf("%T %v\n", mod, mod)
    if mod.(Module) != nil {
        fmt.Println(mod.Name())
        mods[mod.Name()] = mod
    }
}