3 回答
TA贡献1860条经验 获得超8个赞
XYZ 确实实现了 ABC。这与如何确定方法集有关(添加重点):
类型可以具有与其关联的方法集。接口类型的方法集就是它的接口。任何其他类型 T 的方法集由接收者类型 T 声明的所有方法组成。对应指针类型 *T 的方法集是接收者 *T 或 T 声明的所有方法的集合(即还包含接收者类型 T 声明的方法)。集 T)。
方法集决定接口是否实现:
接口类型指定称为其接口的方法集。接口类型的变量可以存储任何类型的值,其方法集是接口的任何超集。这样的类型被称为实现接口。
当调用 时*XYZ.a()
,Go 编译器总是可以自动解引用指针来获取值接收者。这样做没有任何缺点,因为接收者无法修改(就调用者而言)。
当且仅当该值是可寻址时,反逻辑才成立:
type T struct {}
func (*T) M()
func main() {
var t T
t.M() // ok; t is addressable and the compiler rewrites this to (*t).M()
var m map[string]T
m["x"].M() // error: cannot take the address of m["x"]
}
TA贡献1812条经验 获得超5个赞
会出现错误,因为a(*main.XYZ)的类型没有实现接口ABC
错误的。*main.XYZ
实现ABC
(否则abc = xyz
会在编译时失败,尝试将方法重命名b
为c
例如),但该变量a
保存一个nil
指针(类型为*XYZ
)。由于该方法具有值接收器,因此要调用该方法,必须取消XYZ.a()
引用类型的指针值。*XYZ
但是nil
指针不指向任何内容,它不能被取消引用,尝试这样做会导致运行时恐慌,就像您所经历的那样。
如果您xyz
从一开始就使用非nil
指针进行初始化,那么它会起作用:
var xyz *XYZ = new(XYZ)
在Go Playground上尝试一下。
另请注意,如果XYZ.a()
和XYZ.b()
会有指针接收器,那么如果xyz
是nil
:
func (xyz *XYZ) a() string {
return "XYZ"
}
func (xyz *XYZ) b() int {
return 123
}
func main() {
var xyz *XYZ
// ...
在Go Playground上尝试一下。这样做的原因是因为如果接收者是指针,则nil
不必取消引用指针即可调用带有指针接收者的方法,因此不会发生运行时恐慌。当然,如果在方法中您引用XZY.aa
或XYZ.bb
字段,那将是运行时恐慌,但您当前的方法实现不会这样做,所以它可以工作。
TA贡献1811条经验 获得超5个赞
当我在值上调用方法时(不是指针,是实现接口的结构的方法,并且方法的接收者是指针)。Golang会创建一个新对象,并从原始struct值中复制值,然后,iface.data将指向新对象,现在,当我们将新对象的指针传递给方法时,它可以被修改,但是这个操作不会改变原始结构体值,这没有任何用处,因此,当我们将结构体值分配给接口(指针接收者)时,Golang会发生错误
- 3 回答
- 0 关注
- 159 浏览
添加回答
举报