长亭百川云 - 文章详情

Golang 通用万能类型 interface 接口与类型断言

RedTeam

45

2024-07-13

0x00 多态的实现

在聊通用万能类型 interface{} 接口之前,先来谈谈 Golang 中多态的实现与基本要素。

interface 定义抽象方法,子类继承并且实现对应的抽象方法,以达到一个抽象接口有多个不同表现形式的目的,这种现象被称为面向对象的多态。

当我们继承一个类时,需要在 struct 中将父类的名字写下来,如果继承接口的话,则无需将父类的名字写下来,直接将接口包含的抽象方法全部实现即可,此时我们可以直接使用 interface 指针接收(指向)一个子对象。

`package main      import "fmt"      // 本质是一个指针   type AnimalIF interface {    Sleep()    GetColor() string // 获取动物的颜色    GetType() string  // 获取动物的种类   }      // 具体的类   type Cat struct {    color string // 猫的颜色   }      func (this *Cat) Sleep() {    fmt.Println("Cat is Sleep...")   }      func (this *Cat) GetColor() string {    return this.color   }      func (this *Cat) GetType() string {    return "Cat"   }      type Dog struct {    color string   }      func (this *Dog) Sleep() {    fmt.Println("Dog is Sleep...")   }      func (this *Dog) GetColor() string {    return this.color   }      func (this *Dog) GetType() string {    return "Dog"   }      func showAnimal(animal AnimalIF) {    animal.Sleep() // 多态    fmt.Println("color = ", animal.GetColor())    fmt.Println("kind = ", animal.GetType())   }      func main() {    var animal AnimalIF // 接口的数据类型,父类指针    animal = &Cat{"Green"}    animal.Sleep() // 调用的就是 Cat 的 Sleep() 方法       animal = &Dog{"Yellow"}    animal.Sleep() // 调用 Dog 的 Sleep() 方法,多态现象       cat := Cat{"Green"}    dog := Dog{"Yellow"}       showAnimal(&cat)    showAnimal(&dog)   }      `
`go fmt .\main.go   go run .\main.go   `

image

image

0x01 多态的基本要素

  1. 有一个父类(有接口)

  2. 有子类(实现了父类的全部接口方法)

  3. 父类类型的变量(指针)指向(引用)子类的具体数据变量

0x02 通用万能类型 interface{}

通用万能类型 interface{},就是元类,表示空接口,就是所有的 struct 最终都实现了这个空接口。

如 int、string、float32、float64、struct 都实现了 interface{} 空接口,可以使用 interface{} 数据类型引用任意数据类型。

`package main      import "fmt"      func myFunc(arg interface{}) {    fmt.Println("myFunc() is called...")    fmt.Println(arg)   }      type Book struct {    auth string   }      func main() {    book := Book{"Golang"}    myFunc(book)    myFunc(233)    myFunc("tonghuaroot")    myFunc(3.14)   }      `

image

0x03 类型断言

通过类型断言机制,interface{} 可以区分引用的底层数据类型。

`package main      import "fmt"      func myFunc(arg interface{}) {    fmt.Println("myFunc() is called...")    fmt.Println(arg)       value, ok := arg.(string)    if !ok {     fmt.Println("==========")     fmt.Println("arg is not string type")     fmt.Println("value = ", value)     fmt.Printf("value type is %T \n", value) // 在类型断言机制中,如果 arg 不是 string 类型,则 value 值为一个 string 类型的空值(其他类型也适用)     fmt.Println("==========")    } else {     fmt.Println("arg is string type, value = ", value)     fmt.Printf("value type is %T \n", value)    }   }      type Book struct {    auth string   }      func main() {    book := Book{"Golang"}    myFunc(book)    myFunc(233)    myFunc("tonghuaroot")    myFunc(3.14)   }      `

image

0x04 相关疑问

  1. 似乎父类子类之间的继承与接口(抽象类)与子类之间的继承很相似,什么场景下应该采用哪种类型呢?

父类的方法通常也包含了一些功能,子类可以重写父类的方法实现新的功能,接口均为抽象方法,是没有实现的空方法,子类实现该接口时要为这些方法定义对应的功能。如果我们有多态的需求,比如说在调用函数时,形式参数传入接口对象,此时可以依据需求传入不同的子类引用,进而执行不同的功能,这种场景是推荐使用接口与子类这种继承(实现)的,其他情况可以采用父类与子类继承这种模式。

  1. 如果子类除了实现了抽象类的所有方法,又增加了其他的方法,此时算不算实现了接口呢?

算。

`package main      import "fmt"      // 本质是一个指针   type AnimalIF interface {    Sleep()    GetColor() string // 获取动物的颜色    GetType() string  // 获取动物的种类   }      // 具体的类   type Cat struct {    color string // 猫的颜色   }      func (this *Cat) Sleep() {    fmt.Println("Cat is Sleep...")   }      func (this *Cat) GetColor() string {    return this.color   }      func (this *Cat) GetType() string {    return "Cat"   }      type Dog struct {    color string   }      func (this *Dog) Sleep() {    fmt.Println("Dog is Sleep...")   }      func (this *Dog) GetColor() string {    return this.color   }      func (this *Dog) GetType() string {    return "Dog"   }      func (this *Dog) PrintMsg() string {    return "Hmm..."   }      func showAnimal(animal AnimalIF) {    animal.Sleep() // 多态    fmt.Println("color = ", animal.GetColor())    fmt.Println("kind = ", animal.GetType())   }      func main() {    var animal AnimalIF // 接口的数据类型,父类指针    animal = &Cat{"Green"}    animal.Sleep() // 调用的就是 Cat 的 Sleep() 方法       animal = &Dog{"Yellow"}    animal.Sleep() // 调用 Dog 的 Sleep() 方法,多态现象       cat := Cat{"Green"}    dog := Dog{"Yellow"}    fmt.Println("Dog Print Message: ", dog.PrintMsg())       showAnimal(&cat)    showAnimal(&dog)   }      `

image

0x05 References

  1. Type assertions - https://go.dev/tour/methods/15

  2. https://www.bilibili.com/video/BV1gf4y1r79E?p=20

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2