舉例
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