举例
type Poultry interface {
eat()
}
type Bird interface {
Poultry
drink()
}
type Chicken struct {
name string
}
func (b Chicken) eat() {
fmt.Printf("%s eat food!\n", b.name)
}
func (b Chicken) drink() {
fmt.Printf("%s drink water!\n", b.name)
}
type Dog struct {
name string
}
func (d Dog) eat() {
fmt.Printf("%s eat food!\n", d.name)
}
定义两个接口Poultry和Bird,实现Poultry接口需要实现方法eat。实现Bird接口需要实现eat和drink。
现有两个对象Chicken和Dog,Chicken实现了两个方法,所以它断言为Poultry和Bird均能成功;Dog只实现了eat方法,所以它只能断言为poultry方法才能成功。
因此,在写接口断言代码时,需要严格遵守 if x, ok := interfaceX.(typeY);ok{}这样的优雅写法。
代码如下:
func main() {
chicken := Bird(&Chicken{})
dog := Poultry(&Dog{})
if c, ok := chicken.(*Chicken); ok {
c.name = "cc"
chicken.eat()
chicken.drink()
}
if d, ok := dog.(*Chicken); ok {
d.name = "dd"
d.eat()
d.drink()
}
}
输出如下:
cc eat food!
cc drink water!
如果,采用以下形式,会造成程序panic。
错误示范:
func main() {
chicken := Bird(&Chicken{})
dog := Poultry(&Dog{})
c := chicken.(*Chicken)
c.name = "cc"
chicken.eat()
chicken.drink()
d := dog.(*Chicken)
d.name = "dd"
d.eat()
d.drink()
}
造成后果:
cc eat food!
cc drink water!
panic: interface conversion: main.Poultry is *main.Dog, not *main.Chicken
goroutine 1 [running]:
main.main()
/Users/slp/go/src/workspace/example/csdn/main.go:42 +0xac
Process finished with exit code 2
最后,写代码要养成好的习惯。Golang推荐规范参考:https://github.com/uber-go/guide