2.14 Go 之 interface接口理解

go语言并没有面向对象的相关概念,go语言提到的接口和java、c++等语言提到的接口不同,它不会显示的说明实现了接口,没有继承、子类、implements关键词。go语言通过隐性的方式实现了接口功能,相对比较灵活。

interface是go语言的一大特性,主要有以下几个特点:

  • interface 是方法或行为声明的集合
  • interface接口方式实现比较隐性,任何类型的对象实现interface所包含的全部方法,则表明该类型实现了该接口。
  • interface还可以作为一中通用的类型,其他类型变量可以给interface声明的变量赋值。
  • interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。

下面是一些代码示例

接口实现

  1. package main
  2. import "fmt"
  3. type Animal interface {
  4. GetAge() int32
  5. GetType() string
  6. }
  7. type Dog struct {
  8. Age int32
  9. Type string
  10. }
  11. func (a *Dog) GetAge() int32 {
  12. return a.Age
  13. }
  14. func (a *Dog) GetType() string {
  15. return a.Type
  16. }
  17. func main() {
  18. animal := &Dog{Age: 20, Type: "DOG"}
  19. fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge())
  20. }

interface作为通用类型

  1. package main
  2. import (
  3. "fmt"
  4. "reflect"
  5. )
  6. type User struct {
  7. Id int
  8. Name string
  9. Amount float64
  10. }
  11. func main() {
  12. var i interface{}
  13. i = "string"
  14. fmt.Println(i)
  15. i = 1
  16. fmt.Println(i)
  17. i = User{Id: 2}
  18. //i.(User).Id = 15 //运行此处会报错,在函数中修改interface表示的结构体的成员变量的值,编译时遇到这个编译错误,cannot assign to i.(User).Id
  19. fmt.Println(i.(User).Id)
  20. }

注意:

不可用i:=interface{} 这种形式,因为不能确定i的具体类型,会报type interface {} is not an expression 错误。

interface接口查询

接口查询,在一个接口变量中,查询所赋值的对象有没有实现其他接口所有的方法的过程,就是查询接口。即接口A实现了接口B中所有的方法,那么通过查询赋值A可以转化为B。

代码示例

  1. package main
  2. import "fmt"
  3. type Animal interface {
  4. GetAge() int32
  5. GetType() string
  6. }
  7. type AnimalB interface {
  8. GetAge() int32
  9. }
  10. type Dog struct {
  11. Age int32
  12. Type string
  13. }
  14. func (a *Dog) GetAge() int32 {
  15. return a.Age
  16. }
  17. func (a *Dog) GetType() string {
  18. return a.Type
  19. }
  20. func main() {
  21. var animal Animal = &Dog{Age: 20, Type: "DOG"}
  22. fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge())
  23. var animalb AnimalB = &Dog{Age: 20, Type: "DOG"}
  24. fmt.Printf("max age is: %d", animalb.GetAge())
  25. //这里实现了animalb 转化Animal接口
  26. val, ok := animalb.(Animal)
  27. if !ok {
  28. fmt.Println("ok")
  29. } else {
  30. fmt.Printf("%s max age is: %d", val.GetType(), val.GetAge())
  31. }
  32. }

接口转化很简单

  1. val, ok := animalb.(Animal)

注意,animalb 只有AnimalB所包含的方法GetAge()。

如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A,反之则不行。

接口类型查询

只能对interface{}类型的变量使用类型查询

示例

  1. package main
  2. import "fmt"
  3. type Animal interface {
  4. GetAge() int32
  5. GetType() string
  6. }
  7. type AnimalB interface {
  8. GetAge() int32
  9. }
  10. type Dog struct {
  11. Age int32
  12. Type string
  13. }
  14. func (a *Dog) GetAge() int32 {
  15. return a.Age
  16. }
  17. func (a *Dog) GetType() string {
  18. return a.Type
  19. }
  20. func main() {
  21. var i interface{}
  22. //i = "ok"
  23. //方法一
  24. val, ok := i.(Animal)
  25. if !ok {
  26. fmt.Println("no")
  27. } else {
  28. fmt.Println(val.GetAge())
  29. }
  30. // 方法二
  31. switch val := i.(type) {
  32. case string:
  33. fmt.Println(val)
  34. case int:
  35. fmt.Println(val)
  36. default:
  37. fmt.Println(val)
  38. }
  39. // 方法三 通过反射
  40. typename := reflect.TypeOf(i)
  41. fmt.Println(typename)
  42. }

interface默认nil所以查出是nil,如果给i赋值一个字符型值(去掉i = “ok”前面的注释),则返回

no ok string

参考:

https://blog.csdn.net/hzwy23/article/details/57079330

https://www.cnblogs.com/zhangweizhong/p/9526331.html

links

  • 目录
  • 上一节:
  • 下一节: