生产环境遇到一个 Go 问题,整组人都懵圈了...

开发 后端
为什么,这两段 Go 程序是怎么回事...也太反直觉了?其背后的原因本质上还是对 Go 语言中 interface 的基本原理的理解。

[[394588]]

大家好,我是煎鱼。

前段时间正在疯狂写代码的时候,突然有一个读者给我提了一个问题,让我有了一定的兴趣:

[[394589]]

我还是比较感兴趣的,因为是生产环境、有代码,且整组人都懵逼的问题。

在征求了小伙伴的意见后,今天分享出来,大家也思考一下原因,一起规避这个 “坑”。

案例一

代码示例如下:

  1. type MyErr struct { 
  2.     Msg string 
  3.  
  4. func main() { 
  5.     var e error 
  6.     e = GetErr() 
  7.     log.Println(e == nil) 
  8.  
  9. func GetErr() *MyErr { 
  10.     return nil 
  11.  
  12. func (m *MyErr) Error() string { 
  13.     return "脑子进煎鱼了" 

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

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

输出结果如下:

  1. 2021/04/04 08:39:04 false 

答案是:false。

案例二

代码示例如下:

  1. type Base interface { 
  2.     do() 
  3.  
  4. type App struct { 
  5.  
  6. func main() { 
  7.     var base Base 
  8.     base = GetApp() 
  9.      
  10.     log.Println(base) 
  11.     log.Println(base == nil) 
  12.  
  13. func GetApp() *App { 
  14.     return nil 
  15. func (a *App) do() {} 

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

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

输出结果如下:

  1. 2021/04/04 08:59:00 <nil> 
  2. 2021/04/04 08:59:00 false 

答案是: 和 false。

为什么

为什么,这两段 Go 程序是怎么回事...也太反直觉了?其背后的原因本质上还是对 Go 语言中 interface 的基本原理的理解。

在案例一中,虽然 GetErr 方法确实是返回了 nil,返回的类型也是具体的 *MyErr 类型。但是其接收的变量却不是具体的结构类型,而是 error 类型:

  1. var e error 
  2. e = GetErr() 

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

  1. type error interface { 
  2.     Error() string 

因此兜兜转转又回到了 interface 类型的问题,interface 不是单纯的值,而是分为类型和值。

所以传统认知的此 nil 并非彼 nil,必须得类型和值同时都为 nil 的情况下,interface 的 nil 判断才会为 true。

在案例一中,结合代码逻辑,更符合场景的是:

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

输出结果就会是 true。

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

总结

今天这篇文章,相当于是《Go 面试题:Go interface 的一个 “坑” 及原理分析》的变形了,毕竟是生产环境的代码改造而来,更贴合真实的实际场景。

 

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

 

责任编辑:武晓燕 来源: 脑子进煎鱼了
相关推荐

2022-05-31 08:35:05

RocketMQACK客户端

2021-12-09 11:31:16

跨域后端开发

2023-11-15 14:34:05

MySQL悲观锁

2020-12-23 09:04:56

开发双引号数据

2021-07-14 15:06:50

SDK版本 jar

2020-01-10 09:20:03

手机ISOJDK

2021-08-30 08:03:22

信号量Go

2020-04-02 09:31:49

微前端架构系统

2022-04-10 18:10:24

CURD链表

2022-09-27 08:19:20

前端React

2022-11-28 08:37:23

MQ集群线程栈

2022-09-19 08:07:28

Goweb 程序

2021-11-23 15:35:01

程序员Rust开发者

2019-05-23 09:30:22

网络框架数据

2023-02-21 17:06:49

硬件软件系统

2022-11-05 18:08:26

CPUtop 命令

2019-01-07 14:36:36

Go系统开源库

2018-04-12 09:29:56

HTTP服务器问题

2023-05-18 14:08:31

AI开源

2024-01-12 16:20:04

点赞
收藏

51CTO技术栈公众号