Golang接口優雅斷言

舉例

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章