Go踩坑:interface{}判断nil
问题背景
在实习的一次真实程序开发中,我编写了一个函数,其处理一个接口类型(interface{})的参数,根据其类型返回一个字符串。
在传入的参数为nil时,我希望通过判断,返回空字符串。看看我的大致代码:
func main() {
var p *int64
fmt.Println(defaultValueFn(p)) // p未赋值,我希望返回空字符串
}
func defaultValueFn(point interface{}) string {
if point == nil {
return ""
}
var value string
switch v := point.(type) {
case *int64:
value = strconv.FormatInt(*v, 10)
case *time.Time:
value = (*v).Format(time.RFC1123)
case *string:
value = *v
default:
value = ""
}
return value
}
然而我运行时报错:panic: runtime error: invalid memory address or nil pointer dereference
问题分析
我们看src/runtime/runtime2.go源码中如何定义interface:
type eface struct {
_type *_type
data unsafe.Pointer
}
eface结构体表示不含 method 的 interface 结构,有一个字段_type *_type表示类型,有一个字段data unsafe.Pointer指向了这个interface代表的具体数据
问题就是,当我们传入一个空值但type非空的interface时,==nil
判断将返回flase
因此在下面的*v
解包操作会失败
问题解决
分析完问题的产生原因后,这里提供我的一个解决方法,在类型断言成功后,进一步检查指针type是否为 nil
func defaultValueFn(point interface{}) string {
if point == nil {
return ""
}
var value string
switch v := point.(type) {
case *int64:
if v != nil { // 这里进一步判断
value = strconv.FormatInt(*v, 10)
} else {
value = ""
}
case *time.Time:
if v != nil {
value = (*v).Format(time.RFC1123)
} else {
value = ""
}
case *string:
if v != nil {
value = *v
} else {
value = ""
}
default:
value = ""
}
return value
}