我是戈朗的新手。我从 go 之旅开始。这是go playground 链接这是代码:package mainimport "fmt"type I interface { M()}type T struct { S string}func (t *T) M() { fmt.Println(t.S)}func main() { var i I var t *T i = t i.M()}它很恐慌恐慌:运行时错误:无效内存地址或零指针取消引用[信号 SIGSEGV:分段违规代码=0xffffffff 地址=0x0 pc=0xd3ea6] goroutine 1 [运行]:main.(*T).M(0x0, 0x434070) /tmp/ sandbox696069628/main.go:15 +0x26 main.main() /tmp/sandbox696069628/main.go:24 +0x40但是当我改变var t *T i = t到var t T i = &t它不再恐慌在这两种情况下,行为不应该相似吗?如果不是,为什么?
2 回答
ABOUTYOU
TA贡献1812条经验 获得超5个赞
您正在声明但未明确定义t
在两种情况下都命名的变量。如果不指定值,则分配变量类型的零值
所有指针类型的零值,包括*T
nil。结构类型的零值是该结构的所有字段都设置为零值的值。
当为变量 [...] 分配存储并且未提供显式初始化时,变量或值将被赋予默认值。此类变量或值的每个元素都设置为其类型的零值:布尔值为 false,数字类型为 0,字符串为 "",指针、函数、接口、切片、通道和映射为 nil。此初始化是递归完成的,因此,例如,如果未指定值,则结构数组的每个元素都将其字段清零。
https://golang.org/ref/spec#The_zero_value
因此,这会将 nil 存储在接口值中i
:
var i interface{ M() }
var t *T
i = t
// i stores nil
这在接口值中存储了一个结构值i:
var i interface{ M() }
var t T
i = t
// i stores T{S:""}
所以在第一种情况下,(nil).M()被称为(恐慌),在第二种情况下(T{}).M()被称为。
- 2 回答
- 0 关注
- 105 浏览
添加回答
举报
0/150
提交
取消