优雅判断 interface 是否为 nil

简介: 优雅判断 interface 是否为 nil

背景


很久之前发过一篇文章:《10个令人惊叹的Go语言技巧,让你的代码更加优雅》,这篇文章中第八点有一处错误的地方被认真的读者发现了:



于是我有空之后,立马重新看了那篇文章的内容,确实是存在读者所说的问题。


问题


问题就在于下面这句话,文章也是有列出的:

即使接口持有的值为 nil,也不意味着接口本身为 nil



但是在执行以下语句的时候,是有可能报 panic 的:


return reflect.ValueOf(x).IsNil()


而输出也是非常明显的指出错误:


panic: reflect: call of reflect.Value.IsNil on int Value


因为不可 nilinterface 是不能使用 reflect.Value.IsNil 方法。


那么问题就很好解决了。


解决方式


我们在执行 reflect.Value.IsNil 方法之前,进行一次判断是否为指针即可:


func IsNil(x interface{}) bool {
 if x == nil {
  return true
 }
 rv := reflect.ValueOf(x)
 return rv.Kind() == reflect.Ptr && rv.IsNil()
}


重点在于 rv.Kind() == reflect.Ptr && rv.IsNil() 这段代码。


这段代码的作用:


  • 判断 x 的类型是否为指针。
  • 判断 x 的值是否真的为 nil


下面我们使用几种常见的数据类型来进行测试:


func IsNil(x interface{}) bool {
 if x == nil {
  return true
 }
 rv := reflect.ValueOf(x)
 return rv.Kind() == reflect.Ptr && rv.IsNil()
}
func main() {
 fmt.Printf("int IsNil: %t\n", IsNil(returnInt()))
 fmt.Printf("intPtr IsNil: %t\n", IsNil(returnIntPtr()))
 fmt.Printf("slice IsNil: %t\n", IsNil(returnSlice()))
 fmt.Printf("map IsNil: %t\n", IsNil(returnMap()))
 fmt.Printf("interface IsNil: %t\n", IsNil(returnInterface()))
 fmt.Printf("structPtr IsNil: %t\n", IsNil(returnStructPtr()))
}
func returnInt() interface{} {
 var value int
 return value
}
func returnIntPtr() interface{} {
 var value *int
 return value
}
func returnSlice() interface{} {
 var value []string
 return value
}
func returnMap() interface{} {
 var value map[string]struct{}
 return value
}
func returnInterface() interface{} {
 var value interface{}
 return value
}
type People struct {
 Name string
}
func returnStructPtr() interface{} {
 var value *People
 return value
}


我们先后使用了 int*intslicemapinterface{}自定义结构体 来测试此 IsNil 方法。运行程序输出为:


int IsNil: false
intPtr IsNil: true
slice IsNil: false
map IsNil: false
interface IsNil: true
structPtr IsNil: true


从测试结果来看,目前是符合我们对此方法的定位的。

相关文章
|
Cloud Native Java Go
关于 interface{} 会有啥注意事项?上
关于 interface{} 会有啥注意事项?上
|
Web App开发 安全 Windows
解决:对COM 组件的调用返回了错误 HRESULT E_FAIL
  调用SHDOCVW(web浏览器) COM组件的时候,返回了错误 HRESULT E_FAIL。总结如下:     1. 在控制面板--->管理工具--->服务 中,开启Distributed Transaction Coordinator 服务。
6615 0
|
6月前
|
Go
mutex := rs.NewMutex(mutexname) // 对key进行 if err := mutex.Lock(); err != nil { pani
mutex := rs.NewMutex(mutexname) // 对key进行 if err := mutex.Lock(); err != nil { pani
|
7月前
|
Go
Go - struct{} 实现 interface{}
Go - struct{} 实现 interface{}
51 9
Fatal error: Call to undefined function openssl_pkey_get_private()
Fatal error: Call to undefined function openssl_pkey_get_private()
97 0
|
数据安全/隐私保护
Register fail:AuthenticationaFailureException
Register fail:AuthenticationaFailureException
101 1
|
Cloud Native Go
关于 interface{} 会有啥注意事项?下
关于 interface{} 会有啥注意事项?下
|
Serverless
函数计算中,测试代码“failed to match interface”
函数计算中,测试代码“failed to match interface”
147 0
|
SQL 并行计算 数据库连接
ArcSWAT报错:Error Number :-2147467259; 对 COM 组件的调用返回了错误 HRESULT E_FAIL
ArcSWAT报错:Error Number :-2147467259; 对 COM 组件的调用返回了错误 HRESULT E_FAIL
|
数据库
GORM 执行结果判断问题(error nil问题)
GORM 执行结果判断问题(error nil问题)
300 0
GORM 执行结果判断问题(error nil问题)