示例:
package main
import "fmt"
type T1 struct {
id int
}
func (t T1) m1() {
fmt.Println("T1.m1")
}
type T2 struct {
id int
}
func (t T2) m1() {
fmt.Println("T2.m1")
}
type MyStruct struct {
T1
T2
}
func main() {
my := MyStruct{T1{449},T2{554}}
my.m1()
fmt.Printf("%d\n", my.id)
}
输出:
./t.go:28:4: ambiguous selector my.m1
./t.go:29:23: ambiguous selector my.id
Go没有类似Java那样的继承,只能通过结构体的匿名组合来实现继承的特性。这个过程是在编译期完成的,例如上面的示例,假如没有T2的话,那么编译器会给MyStruct创建一个m1方法,然后在方法里调用T1.m1()。
func (m *MyStruct) m1(){
m.T1.m1()
}
但是如果MyStruct又匿名组合了T2,而T2也有m1()方法,则编译器就不知道在给MyStruct创建m1方法时应该选择T1还是T2的m1(), 于是就报错“ambiguous selector”。除了方法以外,结构体的字段也有这种问题,如果没有T2,则编译器会把my.id替换为m.T1.id,如果取值可以确定的情况下,会进一步替换成其取值。而有了T2之后,编译器就不知道该把my.id替换成谁的取值。
因此,需要明确指明调用哪个结构体的m1()方法,读取哪个结构体的id,如下所示:
func main() {
my := MyStruct{T1{449},T2{554}}
my.T1.m1()
fmt.Printf("%d\n", my.T1.id)
}
相关文章: