首页 > 解决方案 > 零指针嵌入错误

问题描述

当我尝试打印带有未初始化嵌入错误的指针时,为什么会出现 nil 指针错误:

package main

import (
  "log"
  "errors"
)

type Danger struct {
  error
}

func main() {
  // the nil pointer issue has to do with struct embedding an error value that is nil
  d := &Danger{}
  log.Println(d)

  d = &Danger{errors.New("foobar")}
  log.Println(d)
}

结果是

2009/11/10 23:00:00 %!v(PANIC=runtime error: invalid memory address or nil pointer dereference)
2009/11/10 23:00:00 foobar

https://play.golang.org/p/fBuN0XonX9v

这是今天面试的时候出现的,面试官和被面试者都想不通。

标签: gonull

解决方案


规范说:

给定一个结构类型 S 和一个定义类型 T,提升的方法包含在结构的方法集中,如下所示:

  • 如果 S 包含嵌入字段 T,则 S 和 *S 的方法集都包含带有接收者 T 的提升方法。*S 的方法集还包括带有接收者 *T 的提升方法。

fmt文档说:

如果操作数实现了错误接口,则会调用 Error 方法将对象转换为字符串,然后根据动词(如果有)的要求对字符串进行格式化。

由此,我们可以得出结论,log.Println(d)将从error字段中调用提升的 Error 方法。

如果该error字段为nil,则调用会发生恐慌。

fmt 文档还说:

如果错误或字符串方法在被打印例程调用时触发了恐慌,则 fmt 包会重新格式化来自恐慌的错误消息,并用它来自 fmt 包的指示来装饰它。

文本%!v(PANIC=runtime error: invalid memory address or nil pointer dereference)是修饰的恐慌值。


推荐阅读