go - 零指针嵌入错误
问题描述
当我尝试打印带有未初始化嵌入错误的指针时,为什么会出现 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
这是今天面试的时候出现的,面试官和被面试者都想不通。
解决方案
规范说:
给定一个结构类型 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)
是修饰的恐慌值。
推荐阅读
- python - 如何在没有完整前向传递的情况下计算深度 CNN 的特征图形状?
- kofax - System.Runtime.InteropServices.COMException:“[24] KdoLib:未知错误。”
- php - 想隐藏“?” 来自 url 但需要来自 url 的密钥
- tsql - 如何使用声明语句更新表
- rabbitmq - 为什么 Android-Things 应用程序在新的 ConnectionFactory 上崩溃
- sql - 在 CTE 查询中,根据检索到的第一个表 ID 计算另一个表中的记录
- python - 从 PyCharm 安装 pandas - 如何应用正确的约定,然后有哪些步骤?
- python - 从 Cosmos DB 查询时延续令牌出现问题
- javascript - JS 事件冒泡防止复选框选中状态
- content-management-system - umbraco 如何找到它的索引?Umbraco 8.0