问题的背景:
Go实现了一个简单但强大的方法和接口概念,基于鸭子类型(duck typing)。方法只能附加到命名类型(结构体或别名)上,而接口是一组方法。这是实现多态和抽象的关键,而无需明确指定实现(implements)。
问题:
从Java或C#转过来的程序员常常期望明确的关键字implements或extends,并且在值接收器和指针接收器方法之间的差异中感到困惑,这导致不可预测的行为和实现接口时的错误。
解决方案:
定义方法和接口:
type User struct { Name string } func (u User) Greet() string { return "Hello, " + u.Name } func (u *User) SetName(name string) { u.Name = name } type Greeter interface { Greet() string }
主要特点:
是否可以为基本类型int或string的类型别名声明方法?
可以,如果这是一个命名类型,例如:
type MyInt int func (m MyInt) Double() int { return int(m) * 2 }
通过指针和值的方法实现接口有什么区别?
如果接口的方法声明为(T),则两者T和*T都实现接口。如果(T),则只有T满足接口。这对于将结构体传递给接受接口的函数至关重要。
接口的“零值”是如何工作的,如果在nil值上调用方法会发生什么?
未初始化的接口变量等于nil,尝试在nil字段上调用方法将会引发恐慌,除非实现了明确的nil指针处理。
类型以指针(*T)方法声明,接口期望值(T)方法,尝试在接口中使用时结构不编译。试图为类型[]User声明方法,而不是User类型。
优点:
缺点:
所有实现接口的方法都根据正确的接收器声明。在不需要的地方不使用接口(在可以使用具体类型的地方,加在需要多态的地方)。
优点:
缺点: