太疯狂了,Go 程序说 nil 不是 nil...

大家好,我是煎鱼。

各位有没有想过一个问题,就是 nil 有没有可能不是 nil?这在 Go 中还真的切切实实的发生了...

今天就由煎鱼带大家一起细细品尝。

背景

我们一起来看看如下代码:

func main() {
 x := reflect.ValueOf(nil)
 fmt.Println(x.IsNil())
}

你觉得输出结果是什么,是 true 吗,还是 false?

不不不,运行结果如下:

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

goroutine 1 [running]:
reflect.Value.IsNil(...)
        ...

程序抛出了异常(panic),告诉我,你在 nil 值上调用 IsNil 方法会出问题...

这可太疯狂了,他说 nil 没法调用 IsNil,那这个方法存在的意义是什么?

新提案

实际上这是 Go 语言之父 Rob Pike 所提出的提案《proposal: reflect: reflect.ValueOf(nil).IsNil() panics; let's make it return true[1]》里发现的 “奇怪” 案例。

如下图:

4c6ba250e91c90ee35d3903d0a7a3db9.png

可能就有同学问了?那什么情况下会是正确显示的,设想的使用案例是:

type s interface{}

func main() {
 var v s
 elem := reflect.ValueOf(&v).Elem()
 println(elem.IsNil())
}

运行结果是 true,能够正确识别。

整体情况就是:nil 不等于 nil,这与我们的传统理解相差甚远,就像 interface 的相比一样折腾开发者的直觉。

原因没有太多的探讨,但这基本是设计上的 “缺陷” 了,当时没有考虑到这一种场景,导致出现了这个问题。

探讨

Go 核心团队的数名成员都进行了探讨,也是比较认同的。Roger Peppe 甚至给出了一个调整思路,如下:

  • reflect.ValueOf(nil) 返回 Value 的零值(就像现在这样)。

  • 对于 Value 的零值,IsNil 返回 true。

  • 对于 Value 的零值,Type 返回 nil。

一般来说,nil Type 代表 "无类型",就像零 Value 代表 "无值 "一样。而 nil 是我们在 Go 中得到的最接近于代表 "无 "的通用方法,所以 IsNil 返回 true 应该是比较合理的。

由于这个变动,许多开发者担心会违反 Go1 的兼容性保证,因此目前还在研讨阶段,需要等待最新的消息。

总结

今天这篇文章我们讲解了除了 interface 对比外,另外一个神奇的 nil 不等于 nil 的现象。在 Go 中,这些案例其实不少,大多被发现的也在源代码上标注了注释(但不是每个人都会去翻源代码的)。

同时一些设计上的漏洞就会由于 Go1 的兼容性保证一直遗留下来,积累许多年后,数量就会非常多。未来 Go2 真的能及时都处理掉吗?

这可能会比较玄学了。

参考资料

[1]

proposal: reflect: reflect.ValueOf(nil).IsNil() panics; let's make it return true: https://github.com/golang/go/issues/51649

推荐阅读:

Go1.18 泛型初探

资料下载

点击下方卡片关注公众号,发送特定关键字获取对应精品资料!

  • 回复「电子书」,获取入门、进阶 Go 语言必看书籍。

  • 回复「视频」,获取价值 5000 大洋的视频资料,内含实战项目(不外传)!

  • 回复「路线」,获取最新版 Go 知识图谱及学习、成长路线图。

  • 回复「面试题」,获取四哥精编的 Go 语言面试题,含解析。

  • 回复「后台」,获取后台开发必看 10 本书籍。

对了,看完文章,记得点击下方的卡片。关注我哦~ 👇👇👇

如果您的朋友也在学习 Go 语言,相信这篇文章对 TA 有帮助,欢迎转发分享给 TA,非常感谢!932809d985ce5d80b92e22d159c79bf3.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值