Go-接口类型详解(定义、实现、接口继承比较等)

「爱情、让人受尽委屈。」 2023-01-15 02:18 272阅读 0赞

目录

简介

结构体

声明/定义

实现与使用

实现

多接口实现

接口继承

空接口

结构体切片排序

接口和继承比较

注意项

全部代码

截图

参考


简介

Go 语言中的接口是一种内置的类型,它定义了一组方法的签名,体现了程序设计的高内聚低耦合的特点,本篇文章会介绍接口及基本使用,下篇文章介绍类型断言。

结构体

定义Monkey结构体,具有climb方法。

  1. type Monkey struct {
  2. Name string
  3. }
  4. func (m *Monkey)climb(){
  5. fmt.Println(m.Name,"会爬树...")
  6. }

定义WuKong结构体,包含Monkey和Tool属性。

  1. type WuKong struct {
  2. Monkey
  3. Tool string
  4. }

声明/定义

定义接口模板如下:

/* 定义接口 */
type interface_name interface {
method_name1([parameter list]) (return_type)
method_name2 ([parameter list]) (return_type)

method_namen([parameter list]) (return_type)
}

代码

定义Flyable接口

  1. type Flyable interface {
  2. Fly()
  3. }

实现与使用

实现

实现了接口的所有方法,就是实现了该接口,不需要显示指明是哪个接口,即隐式实现

  1. func (w *WuKong) Fly() {
  2. fmt.Println("筋斗云,来...")
  3. }

鸭子类型

鸭子类型duck typing)是动态类型的一种风格,例如,Python语言中比较常见。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由”当前方法和属性集合“决定。

而在Go中,就是由当前结构体的方法集合决定当前结构体是否实现了某个接口。WuKong可以飞,而Monkey不可以飞,WuKong在继承Monkey的基础上,扩展了自己的功能。

多接口实现

再定义一个接口

  1. type Swimmable interface {
  2. Swim()
  3. }

实现

  1. func (w *WuKong) Swim() {
  2. fmt.Println("老龙王,俺老孙的金箍棒呢?")
  3. }

WuKong结构体就实现了上面的两个接口。

接口继承

再定义一个接口Skills,继承前面的两个接口,并添加新的方法Change

  1. type Skills interface {
  2. Flyable
  3. Swimmable
  4. Change()
  5. }

实现

  1. func (w *WuKong) Change() {
  2. fmt.Println("看我72变...")
  3. }

至此, WuKong结构体实现了四个接口,为什么是四个呢?因为还有下面这一个

空接口

  1. type Null interface {
  2. }

如你所见,什么方法也没有,即每个结构体都实现了空接口,都可以赋值给空接口,这在排序,后面类型断言等部分都很有用。

结构体切片排序

func Sort(data Interface)

Sort,本地排序data,无返回。它调用1次data.Len确定长度,调用O(n*log(n))次data.Less和data.Swap,底层使用的是快排,感兴趣的朋友可以看看快排源代码。本函数不能保证排序的稳定性(即不保证相等元素的相对次序不变)。

  1. // Sort sorts data.
  2. // It makes one call to data.Len to determine n and O(n*log(n)) calls to
  3. // data.Less and data.Swap. The sort is not guaranteed to be stable.
  4. func Sort(data Interface) {
  5. n := data.Len()
  6. quickSort(data, 0, n, maxDepth(n))
  7. }

Interface接口

  1. type Interface interface {
  2. // Len is the number of elements in the collection.
  3. Len() int
  4. // Less reports whether the element with index i must sort before the element with index j.
  5. // See Float64Slice.Less for a correct implementation for floating-point values.
  6. Less(i, j int) bool
  7. // Swap swaps the elements with indexes i and j.
  8. Swap(i, j int)
  9. }

既然这是一个接口,只要我们实现了Len、Less、Swap方法即可传参,进行排序。

我们就用Monkey结构体的切片实现一下这个接口。

  1. type MonkeySlice []Monkey
  2. //--------实现Len--------
  3. func (m MonkeySlice) Len() int{
  4. return len(m)
  5. }
  6. //---------实现Less---------
  7. func (m MonkeySlice) Less(i,j int) bool {
  8. return m[i].Name < m[j].Name
  9. }
  10. //----------实现Swap---------
  11. func (m MonkeySlice) Swap(i,j int){
  12. m[i],m[j] = m[j],m[i]
  13. }

使用

  1. monkeys := MonkeySlice{
  2. {"峨眉猴"},{"齐天大圣"},{"金丝猴"},{"六耳猕猴"},{"孙悟空"}}
  3. sort.Sort(monkeys)
  4. fmt.Println(monkeys)

接口和继承比较

  • A结构体继承了B结构体,那么A结构体就自动的继承了B结构体的字段和方法,并且可以直接使用
  • 当A结构体需要扩展功能,同时不希望去破坏继承关系,则可以去实现某个接口即可,
  • 接口是对继承的补充,是like和is的区别
  • 继承解决代码的复用性和可维护性
  • 接口更加灵活,一定程度上实现了解耦

注意项

  • 接口不能创建实例,接口可以指向实现了接口的结构体实例
  • 结构体必须实现所有接口的方法才可以说实现了该接口
  • 接口默认是指针类型,没有初始化会输出nil
  • 空接口可以接收任何类型

全部代码

  1. package main
  2. import (
  3. "fmt"
  4. "sort"
  5. )
  6. type Monkey struct {
  7. Name string
  8. }
  9. func (m *Monkey)climb(){
  10. fmt.Println(m.Name,"会爬树...")
  11. }
  12. //--------Flyable接口---------
  13. type Flyable interface {
  14. Fly()
  15. }
  16. //--------Swimmable接口-------
  17. type Swimmable interface {
  18. Swim()
  19. }
  20. //----------接口继承--------------
  21. type Skills interface {
  22. Flyable
  23. Swimmable
  24. Change()
  25. }
  26. //-----------空接口-----------
  27. type Null interface {
  28. }
  29. //---------不破坏结构体,添加属性--------
  30. type WuKong struct {
  31. Monkey
  32. Tool string
  33. }
  34. //---------不破坏继承,扩展行为/方法--------
  35. func (w *WuKong) Fly() {
  36. fmt.Println("筋斗云,来...")
  37. }
  38. func (w *WuKong) Swim() {
  39. fmt.Println("老龙王,俺老孙的金箍棒呢?")
  40. }
  41. func (w *WuKong) Change() {
  42. fmt.Println("看我72变...")
  43. }
  44. type MonkeySlice []Monkey
  45. //--------实现Len--------
  46. func (m MonkeySlice) Len() int{
  47. return len(m)
  48. }
  49. //---------实现Less---------
  50. func (m MonkeySlice) Less(i,j int) bool {
  51. return m[i].Name < m[j].Name
  52. }
  53. //----------实现Swap---------
  54. func (m MonkeySlice) Swap(i,j int){
  55. m[i],m[j] = m[j],m[i]
  56. }
  57. func main() {
  58. //-----------接口体-------
  59. w := WuKong{}
  60. w.Name = "孙悟空"
  61. //-----------使用方法------
  62. w.climb()
  63. //-----------使用实现的接口的方法---------
  64. w.Fly()
  65. //-----------结构体赋值给接口------------
  66. var s Skills
  67. s = &w
  68. s.Change()
  69. //----------空接口-------------
  70. var null Null
  71. null = w
  72. wukong := null.(WuKong)
  73. wukong.Swim()
  74. //-----------结构体切片排序--------------
  75. monkeys := MonkeySlice{
  76. {"峨眉猴"},{"齐天大圣"},{"金丝猴"},{"六耳猕猴"},{"孙悟空"}}
  77. sort.Sort(monkeys)
  78. fmt.Println(monkeys)
  79. }

截图

20210424185032965.PNG

参考

Go标准库-sort

更多Go相关内容:Go-Golang学习总结笔记

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

发表评论

表情:
评论列表 (有 0 条评论,272人围观)

还没有评论,来说两句吧...

相关阅读