但是,在Go语言中,Expression.Name()
语法要调用的函数完全由表达式的类型决定,而不是由该表达式的特定运行时值决定,包括nil-copied
因此我们可以使用nil的struct实例调用method
。
考虑以下程序:
package main
import "fmt"
type T struct {
V int
tt *T
}
func (t *T) hello() string {
return "world"
}
func main() {
var t *T = nil
fmt.Println(t, t.hello()) // <nil> world
fmt.Println(t, t.tt.hello()) // panic
}
fmt.Println(t, t.hello())
为什么起作用?
但是
fmt.Println(t, t.tt.hello())
感到惊慌?
我的理解是t
和t.tt
都是nil
指针。因此t.tt.hello()
不应惊慌,因为golang中允许在nil struct指针上调用方法。
答案 0 :(得分:3)
准确地说,t
是nil指针,t.tt
根本不存在。您看到的恐慌是取消引用t
而不是t.tt
的结果。 t.tt
也是(或者如果初始化t
也是指针)这一事实也掩盖了这一点。
可以通过访问V
的{{1}}字段来使其更加清楚:
t
第一次测试不会出现恐慌的原因是,在func (t *T) foo() {
fmt.Println(t.V) // Will panic, if `t` is nil
}
上调用方法实际上并未取消引用t
。调用t
与调用t.Hello()
大致相同,因此除非/直到在函数中实际取消引用Hello(t)
,否则不会惊慌。
答案 1 :(得分:2)
我的理解是t和t.tt都是nil指针。所以 t.tt.hello()不应惊慌,因为在nil结构上调用方法 golang中允许使用指针。
您的“理解”是错误的。t.tt
应该并且确实panic
。
Go 1.2 Release Notes (December 2013)
出于安全原因,该语言现在规定, 确保nil个指针会触发运行时恐慌。例如, 在Go 1.0中,给定的代码如
type T struct { X [1<<24]byte Field int32 } func main() { var x *T ... }
nil指针x可能用于错误地访问内存: 表达式x.Field可以访问地址1 << 24的内存。阻止 这种不安全的行为,在Go 1.2中,编译器现在保证 通过nil指针进行间接访问,例如此处所示 在nil指向数组的指针,nil接口值,nil切片等中 开启时,将会恐慌或返回正确的安全非零值。在 简短的,任何显式或隐式要求的表达式 评估一个零地址是一个错误。实施可能会注入 对编译的程序进行额外的测试以强制执行此行为。
更多详细信息在design document中。
简而言之,任何显式或隐式要求的表达式 评估零地址是错误的。
因此,预期以下行为。通过t.tt
的{{1}}值对nil
进行的间接操作失败,并显示t
。
panic
游乐场:https://play.golang.org/p/Szwx5MqNHkQ
输出:
package main
import "fmt"
type T struct {
V int
tt *T
}
func (t *T) hello() string {
return "world"
}
type A struct {
a int
}
func main() {
var t *T = nil
fmt.Println(t) // nil
fmt.Println(t.tt.hello()) // panic
}
答案 2 :(得分:2)
t
为nil,没有t.tt
。
t.hello()
就像hello(t)
,hello(nil)
不会惊慌,但t.tt
会惊慌。
Remember: a method is just a function with a receiver argument.
答案 3 :(得分:-1)
nil
是指针的零值
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
来源:https://golang.org/src/builtin/builtin.go?h=nil#L101
要了解nil
,该视频太棒了
https://www.youtube.com/watch?v=ynoY2xz-F8s