2017-02-14 142 views
1

下面是一些代码:v == nil如何返回false和reflect.ValueOf(v).IsNil()同时返回true?

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

输出是:

VAL是零

v不是零

这怎么可能?是否无?

另外,如果你改变了前两行与

v := (*string)(nil) 

则输出明确指出,变量是零。

现在在我的项目中,我有一个函数接受一个interface {}类型的参数,并且我无法可靠地检查它是否为nil,并带有一个简单的v == nil。我想避免使用反射包。

+0

相关/可能重复[隐藏nil值,了解为什么golang在这里失败](http://stackoverflow.com/questions/29138591/hiding-nil-values-understanding-why-golang-fails-here/29138676# 29138676)。 – icza

回答

3

From golang.org

在内部,接口被实现为两个元件,一个类型 和值。称为接口动态值的值是任意具体值,类型是该值的值。对于int值为3的 ,接口值示意性地包含(int,3)。

仅当内部值和类型都为 未设置(零,零)时,接口值为零。特别是,一个零接口将始终保持一个无类型的 。如果我们在接口 值内存储一个类型为* int的零指针,则无论 指针的值(* int,nil)如何,内部类型都将是* int。即使内部指针为零,这样一个接口值也不会为零,因此是 。

您可以试试fmt.Printf("(%v, %T)\n", v, v)。它打印(<nil>, *string)

当您将前两行更改为v := (*string)(nil)时,v只是一个指针,而不是接口。