生产环境遇到 Go 问题,代码案例

案例一

代码示例如下:

type MyErr struct {
    Msg string
}

func main() {
    var e error
    e = GetErr()
    log.Println(e == nil)
}

func GetErr() *MyErr {
    return nil
}

func (m *MyErr) Error() string {
    return "脑子进煎鱼了"
}

请思考一下,这段程序的输出结果是什么?

该程序所调用的 GetErr 方法所返回的是 nil,而外部判断是 e == nil,因此最终的输出结果是 true,对吗?

输出结果如下:

2021/04/04 08:39:04 false

答案是:false。

案例二

代码示例如下:

type Base interface {
    do()
}

type App struct {
}

func main() {
    var base Base
    base = GetApp()
    
    log.Println(base)
    log.Println(base == nil)
}

func GetApp() *App {
    return nil
}
func (a *App) do() {}

请思考一下,这段程序的输出结果是什么?

该程序调用了 GetApp 方法,该方法返回的是 nil,因此其赋值的 base 也是 nil。因此判断 base == nil 的最终输出结果是 和 true,对吗?

输出结果如下:

2021/04/04 08:59:00 <nil>
2021/04/04 08:59:00 false

答案是: 和 false。

为什么

为什么,这两段 Go 程序是怎么回事…也太反直觉了?其背后的原因本质上还是对 Go 语言中 interface 的基本原理的理解。
在案例一中,虽然 GetErr 方法确实是返回了 nil,返回的类型也是具体的 *MyErr 类型。但是其接收的变量却不是具体的结构类型,而是 error 类型:

var e error
e = GetErr()

在 Go 语言中, error 类型本质上是 interface:

type error interface {
    Error() string
}

因此兜兜转转又回到了 interface 类型的问题,interface 不是单纯的值,而是分为类型和值。
所以传统认知的此 nil 并非彼 nil,必须得类型和值同时都为 nil 的情况下,interface 的 nil 判断才会为 true。
在案例一中,结合代码逻辑,更符合场景的是:

var e *MyErr
e = GetErr()
log.Println(e == nil)

输出结果就会是 true。
在案例二中,也是一样的结果,原因也是 interface。不管是 error 接口(interface),还是自定义的接口,背后原理一致,自然也就结果一致了。

总结

下意识的直觉有时候不是绝对正确的,我们要正确的理解 Go 语言中的那些知识点,才能更好地实现早下班的理想和愿景。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mldxxxxll5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值