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

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