英文:
Weird nil / not-nil behavior
问题
我在我的项目中有以下代码:
mod := srt.PrimaryModule()
if mod != nil {
mods[mod.Name()] = mod
}
当执行时,我得到以下错误:
PANIC: runtime error: invalid memory address or nil pointer dereference
错误发生在第三行的mod
解引用处。(是的,就是mod
解引用,mods
映射在上一行创建了...)
那么,什么时候一个nil值不等于nil呢?为什么会这样?
srt.PrimaryModule()
返回一个接口类型Module
,其中定义了一个返回string
类型的Name()
方法。
在这个特定的情况下,srt
被定义为StdReflectedType
类型,它是一个带有返回类型为Module
的PrimaryModule()
函数的接口类型。srt
的实际实现是一个返回未初始化的Module
值的结构体。
此外,如果我执行
reflect.ValueOf(mod)
结果是零值的reflect.Value
。
根据reflect包的文档:
ValueOf返回一个新的Value,该值初始化为接口i中存储的具体值。ValueOf(nil)返回零值。
这似乎是正确的,但前一行刚刚确定了mod != nil
。这是怎么回事?
我似乎无法在一个最小的示例中重现这个问题 - 是否有任何合理的行为可以导致这些行出现这种情况 - 我是否没有理解接口值和nil指针的一些重要内容?
英文:
I have the following code in my project:
mod := srt.PrimaryModule()
if mod != nil {
mods[mod.Name()] = mod
}
When it executes, I get:
PANIC: runtime error: invalid memory address or nil pointer dereference
with the stack right at the third line of that. (Yes it's the mod
dereference, the map mods
is created just a line above...)
So, when is a nil value not equal to nil? And why?
srt.PrimaryModule()
returns an interface type, Module
, with a Name()
method defined returning string
.
In this particular case, srt
is typed StdReflectedType
, which is an interface type with a function PrimaryModule()
returning type Module
. The actual implementation of srt
is a struct that returns an uninitialized Module
value from its fields.
Further, if I do
reflect.ValueOf(mod)
the result is the zero reflect.Value.
From the reflect package documentation:
ValueOf returns a new Value initialized to the concrete value stored in the interface i. ValueOf(nil) returns the zero Value
Which seems right, except the previous line just determined mod != nil
. So what gives?
I cannot seem to reproduce this in a minimal example - is there any sensible behavior that could cause those lines to do this - am I not understandig something important about interface values and nil pointers?
答案1
得分: 2
如果接口中存储了任何具体值,接口将不是nil
。然而,存储在接口中的具体值可以是nil
指针。
例如,在fmt.Println(mod)
的输出中,具体值是否为nil
?
if mod != nil {
fmt.Println(mod)
mods[mod.Name()] = mod
}
srt.PrimaryModule()
返回一个指向mod
的nil
指针吗?如果是这样,mod.Name()
将会因为nil指针解引用
而引发panic
。
参考资料:
这个代码的修订版本的输出是什么?
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
}
}
英文:
if any concrete value has been stored in the interface, the interface will not be nil
. However, the concrete value stored in the interface can be a nil
pointer.
For example, is the fmt.Println(mod)
output, the concrete value, nil
?
if mod != nil {
fmt.Println(mod)
mods[mod.Name()] = mod
}
Does srt.PrimaryModule()
return a nil
pointer to mod
? If so, mod.Name()
will panic
with a nil pointer dereference
.
References:
The Go Programming Language Specification: Interface types
Go Data Structures: Interfaces
Why is my nil error value not equal to nil?
What is the output from this revised version of your code?
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
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论