我们优雅判断 interface 是否为 nil

开发 前端
我们先后使用了 int、*int、slice、map、interface{}、自定义结构体​ 来测试此 IsNil 方法。

背景

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

图片图片

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

问题

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

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

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

return reflect.ValueOf(x).IsNil()

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

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

因为不可 nil 的 interface 是不能使用 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、*int、slice、map、interface{}、自定义结构体 来测试此 IsNil 方法。运行程序输出为:

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

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

责任编辑:武晓燕 来源: 爱发白日梦的后端
相关推荐

2016-05-24 10:30:56

网站设计出色

2020-11-12 06:03:54

IP IPv4IPv6

2020-10-22 08:06:05

JavaScrip语言类型

2024-06-12 09:52:00

2020-10-22 14:00:31

JavaScript数字变量

2021-12-27 08:53:23

Go函数 Nil

2017-02-08 11:30:51

PHP判断数组

2022-01-03 20:13:08

Gointerface 面试

2022-08-25 14:48:11

变量前端

2010-06-01 15:20:11

MySQL表单

2009-12-16 14:51:26

Ruby nil

2015-03-13 09:36:09

NULLnullptr

2021-12-02 07:25:58

ASP.NET CorAjax请求

2009-12-01 10:00:51

PHP判断字符串是否为

2015-05-28 09:52:21

PHP判断数组为空

2023-11-30 07:40:05

URLCMS

2021-01-04 09:12:31

集合变量

2023-02-21 15:19:25

JavaScriptypeof数据类型

2010-10-11 16:05:37

mysql表单

2010-03-24 09:29:30

Python os.l
点赞
收藏

51CTO技术栈公众号