大家好,我是建宇。前段时间在疯狂写代码的时候,突然有个读者问了我一个问题,让我产生了兴趣:我还是比较感兴趣的,因为是生产环境,有代码,整个群都在纠结这个问题。征求了小伙伴们的意见后,今天分享出来。大家也应该想一想原因,一起避开这个“坑”。Case1的代码示例如下:string{return"我脑子炸了"}请大家想一想,这个程序的输出是什么?本程序调用的GetErr方法返回nil,外部判断为e==nil,所以最终输出为true,对吧?输出如下:2021/04/0408:39:04false答案是:false。Case2的代码示例如下:typeBaseinterface{do()}typeAppstruct{}funcmain(){varbaseBasebase=GetApp()log.Println(base)log.Println(base==nil)}funcGetApp()*App{returnnil}func(a*App)do(){}请想一想,这个程序的输出是什么?此程序调用GetApp方法,该方法返回nil,因此其赋值的基数也为nil。所以判断base==nil最后的输出是andtrue对不对?输出如下:2021/04/0408:59:002021/04/0408:59:00false答案是:andfalse。为什么为什么,这两个Go程序是怎么回事……太反直觉了?其背后的原因本质上是对Go语言中接口基本原理的理解。在情况1中,虽然GetErr方法确实返回了nil,但是返回的类型也是一个特定的*MyErr类型。但是它接收到的变量并不是具体的结构类型,而是错误类型:varererror=GetErr()在Go语言中,错误类型本质上是一个接口:typeerrorinterface{Error()string},所以又回到了接口绕过之后的type问题是接口不是简单的值,而是分为类型和值。所以按照传统的认知,这个nil不是另一个nil。只有类型和值同时为nil时,接口的nil判断才会为真。案例一,结合代码逻辑,更适合场景:vare*MyErre=GetErr()log.Println(e==nil)输出会为true。情况2,结果是一样的,原因也是interface。不管是错误接口(interface)还是自定义接口,其背后的原理都是一样的,结果自然也是一样的。总结今天的文章,相当于对《Go 面试题:Go interface 的一个 “坑” 及原理分析》的一次改造。毕竟是生产环境的代码改造,更适合真实的实际场景。有时潜意识的直觉并不是绝对正确的。我们需要正确理解Go语言中的知识点,才能更好地实现早日下班的理想和愿景。