golang 反射_记录一个golang的nil类型有意思的case

本文探讨了Go语言中空结构体指针引发的panic问题,通过实例展示了即使item为空指针,其绑定的函数依然可以执行,但访问字段会导致panic。作者通过反射和接口的实验,揭示了结构体空指针与普通nil的区别,以及空接口变量的特性。文章引发了对Go语言interface底层结构、结构体与接口关系以及函数调用机制等深入问题的思考。
摘要由CSDN通过智能技术生成

背景

定位线上服务panic的问题,捕获的panic栈日志显示某一行出现nil指针操作,很常见的一个panic问题,去定位到项目中该行代码,发现有好两处对指针的操作,类似如下的操作

type 

本以为很简单,item为空指针,不能对其进行操作。但是,突然发现一个有意思的现象,item.Add函数竟然执行成功了,导致panic的原因是后面的item.A。如果你看到这里,觉得这不是大家都知道的事情吗,那就不用往下看了。

原因探索

其实仔细思考下,原因也很简单,item虽然值为nil,但是它的类型是Item,Item类型绑定了Add函数,而且Add并没有方位对象的任何变量,只是单纯的对参数做了加法返回,而导致panic的item.A 是因为访问了对象,接下来我们通过实际操作,一一验证我们的想法。

验证

  • 代码
package 

运行结果

0a04cf7bebb01335d6b237c86a3c5e05.png

结论

我们通过反射,看出结构体空指针与普通的nil还是不同的,结构体指针的类型是可以获取到的,相应的它对应的函数应该可以执行。

  • 代码
package 

运行结果

3b29244277e2ebb2f55fb756a7f5cfe7.png

结论

这次我们命名了一个接口,并且创建了一个空的接口变量,发现它的类型和value竟然与真正的nil完全相同,至于为什么,可能需要单独写一篇有关interface的结构的文章来解释。但是在这里我们大致可以理解,空的接口变量,与实现该接口的结构体的空指针是完全不同的。结构体空指针应该是在某个地方存着该结构体的函数变量,而空的接口变量对应的函数指针是nil。

  • 代码
package 

运行结果

4c4d46f5fb50e64acf6da0837e03bd28.png

结论

这就比较明显了,虽然空的结构体指针可以调用对应的函数,但是绝对不能访问其内部字段。

我们在来看一个比较有意思的事情。

  • 代码
package 

运行结果

ac95a71741c38791b99938517df30c6c.png

结论

其实也比较好理解,我们把一个空指针,强转成一个*AA类型,必然给它附上了对应的函数指针,它就跟纯nil不太一样了。

最后

其实,在实验的过程中产生了很多的疑问,我会在后续的文章给出一一解答。

  1. golang 的interface底层是什么结构?(其实有iface与eface两种,区别为是否包含函数)
  2. golang的结构体与interface又是什么联系,结构体绑定函数后就可以作为interface,golang的编译器在绑定函数的时候做了什么?
  3. golang的结构体的函数存在哪里,函数调用的时候是如何找到的?
  4. golang的结构体的函数绑定有值绑定与指针绑定,区别是什么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值