优雅判断 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


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

相关文章
|
存储 C语言 C++
37.【C/C++ 静态数据成员和静态成员函数 (超详解)】
37.【C/C++ 静态数据成员和静态成员函数 (超详解)】
336 0
|
5月前
|
XML 前端开发 JavaScript
|
6月前
|
存储 人工智能 物联网
云计算助力医疗信息化,推动智慧医疗新模式。
云计算正深刻改变医疗行业,通过高效数据存储、管理与共享,优化医疗资源分配,推动远程医疗发展。它解决了“数据孤岛”问题,强化了数据安全与隐私保护,同时助力智慧医疗建设,降低信息化成本并提升服务效率。未来,云计算将与5G、AI等技术融合,进一步促进医疗服务智能化与规范化,为医疗行业带来全新可能。
316 7
|
7月前
|
开发者 索引
HarmonyOS使用系统图标
HarmonyOS图标符号是系统内置的图标资源库,开发者可通过SymbolGlyph和SymbolSpan组件高效引用图标资源,简化开发流程并确保应用与系统设计风格一致。通过`$r('sys.symbol.resource_name')`访问系统图标资源,支持调整大小、颜色、粗细、渲染策略及动效。更多示例和学习资料详见官方文档和教程。
336 2
HarmonyOS使用系统图标
|
12月前
|
存储 JavaScript 前端开发
webSocket+Node+Js实现在线聊天(包含所有代码)
文章介绍了如何使用WebSocket、Node.js和JavaScript实现在线聊天功能,包括完整的前端和后端代码示例。
624 0
|
7月前
|
缓存 安全 数据可视化
如何让私有化部署不影响用户体验?产品经理必读指南
本文探讨了在数字化产品竞争中,用户体验(UX)与用户界面(UI)设计对产品成功的重要性。合理的UX设计能降低学习成本、提高效率,出色的UI设计则增强视觉吸引力和易用性。同时,随着数据安全需求提升,私有化部署成为企业重要考量。文章从用户导向设计、简化交互、优化性能等方面阐述如何提升用户体验,并结合私有化部署需求,探讨安全与体验的平衡点,确保产品既安全又易用。
|
存储 小程序 索引
小程序跨页面传递参数的几种方式
小程序跨页面传递参数的几种方式
671 0
|
数据可视化 PyTorch 算法框架/工具
Transformers 4.37 中文文档(五)(3)
Transformers 4.37 中文文档(五)
167 0
|
弹性计算 网络协议 文件存储
将Windows系统机器加入AD域
一台Windows服务器需要加入到Active Directory域后才能通过AD域服务来管理。本文介绍了如何将一台Windows服务器加入已有的AD域。
5106 0
将Windows系统机器加入AD域
|
安全 Java 开发者
JAVA 获取微信用户信息,看完这篇你必须得学会
JAVA 获取微信用户信息,看完这篇你必须得学会
1231 0
JAVA 获取微信用户信息,看完这篇你必须得学会