文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
选择器
对于一个 x 不是包名的主要表达式,选择器表达式:
x.f
表示 x 的字段或方法 f(有时为 *x)。标识符 f 叫做(字段/方法)选择器。它不能是空标识符。选择器表达式的类型就是 f 的类型。如果 x 是包名。请参考修饰标识符。
选择器 f 可以表示类型 T 的方法或字段 f。也可以表示类型 T 的嵌入方法或字段 f。访问 f 所需穿过的嵌套层数叫做它在类型 T 中的深度。声明在 T 中的字段或方法的深度为 0。声明在 T 的嵌入字段 A 中的方法或字段的深度等于 f 在 A 中的深度加一。
选择器遵循以下原则:
对于非指针/接口类型 T/*T 的值 x,x.f 表示第一层的方法/字段。如果在第一层没有对应的 f,选择器表达式就是非法的。
对于接口类型 I 的值 x,
x.f
表示动态值 x 的方法名 f。如果接口 I 的方法集中没有 f 方法,选择器就是非法的。作为例外,如果 x 是一个指针类型并且 (*x).f 是合法的选择器表达式(只能表示字段,不能表示方法)。那么(*x).f 可以简写成 x.f。
在其他情况下,x.f 都是非法的。
如果 x 是指针类型,并且值为 nil,其中 f 为结构体字段。赋值或取值 x.f 会引起运行时恐慌。
如果 x 是接口类型,并且值为 nil。调用 x.f 会引起运行时恐慌。
例如给定声明:
type T0 struct {
x int
}
func (*T0) M0()
type T1 struct {
y int
}
func (T1) M1()
type T2 struct {
z int
T1
*T0
}
func (*T2) M2()
type Q *T2
var t T2 // with t.T0 != nil
var p *T2 // with p != nil and (*p).T0 != nil
var q Q = p
结果:
t.z // t.z
t.y // t.T1.y
t.x // (*t.T0).x
p.z // (*p).z
p.y // (*p).T1.y
p.x // (*(*p).T0).x
q.x // (*(*q).T0).x (*q).x is a valid field selector
p.M0() // ((*p).T0).M0() M0 expects *T0 receiver
p.M1() // ((*p).T1).M1() M1 expects T1 receiver
p.M2() // p.M2() M2 expects *T2 receiver
t.M2() // (&t).M2() M2 expects *T2 receiver, see section on Calls
但是下面这种方式是不合法的:
q.M0() // (*q).M0 is valid but not a field selector
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论