英文:
How can v == nil return false and reflect.ValueOf(v).IsNil() return true at the same time?
问题
这是一些代码:
var v interface{}
v = (*string)(nil)
// 反射显示它是 nil
val := reflect.ValueOf(v)
if val.IsNil() {
fmt.Println("val 是 nil")
} else {
fmt.Println("val 不是 nil")
}
// 这里显示它不是 nil
if v == nil {
fmt.Println("v 是 nil")
} else {
fmt.Println("v 不是 nil")
}
https://play.golang.org/p/apyPa4CNZ6
输出结果是:
val 是 nil
v 不是 nil
这是怎么可能的?v 是 nil 还是不是?
另外,如果你将前两行改为:
v := (*string)(nil)
那么输出明确表示变量是 nil。
我目前的项目中有一个接受 interface{} 类型参数的函数,我无法可靠地通过简单的 v == nil 来检查它是否为 nil。我希望避免使用 reflect 包。
英文:
Here's some code:
var v interface{}
v = (*string)(nil)
// Reflect says it is nil
val := reflect.ValueOf(v)
if val.IsNil() {
fmt.Println("val is nil")
} else {
fmt.Println("val is not nil")
}
// This says it is not nil
if v == nil {
fmt.Println("v is nil")
} else {
fmt.Println("v is not nil")
}
https://play.golang.org/p/apyPa4CNZ6
The output is:
> val is nil
>
> v is not nil
How is this possible? Is v nil or not?
Also, if you change the first two lines with
v := (*string)(nil)
then the output clearly states that the variable is nil.
Right now in my project I have a function that accepts a argument of type interface{} and I can't reliably check if it is nil with a simple v == nil. I would like to avoid using the reflect package.
答案1
得分: 4
> 在底层,接口由两个元素实现,一个是类型,一个是值。值被称为接口的动态值,是一个任意的具体值,而类型则是该值的类型。对于int值3,接口值包含了(int,3)的示意图。
>
> 只有当内部值和类型都未设置时,接口值才为nil,即(nil,nil)。特别地,nil接口将始终持有一个nil类型。如果我们将类型为int的nil指针存储在接口值中,无论指针的值如何,内部类型都将是int:(*int,nil)。因此,即使内部指针为nil,这样的接口值也将是非nil的。
你可以尝试使用fmt.Printf("(%v, %T)\n", v, v)
。它会打印出(<nil>, *string)
。
当你将前两行改为v := (*string)(nil)
时,v
只是一个指针,而不是一个接口。
英文:
> Under the covers, interfaces are implemented as two elements, a type
> and a value. The value, called the interface's dynamic value, is an
> arbitrary concrete value and the type is that of the value. For the
> int value 3, an interface value contains, schematically, (int, 3).
>
> An interface value is nil only if the inner value and type are both
> unset, (nil, nil). In particular, a nil interface will always hold a
> nil type. If we store a nil pointer of type *int inside an interface
> value, the inner type will be *int regardless of the value of the
> pointer: (*int, nil). Such an interface value will therefore be
> non-nil even when the pointer inside is nil.
You can try fmt.Printf("(%v, %T)\n", v, v)
. It prints (<nil>, *string)
.
When you change first two lines to v := (*string)(nil)
, v
is just a pointer, not an interface.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论