Go接口的使用

Duck Typing

Go语言通过接口(interface),实现了Duck Typing。它是一种抽象类型,描述代表了一组方法的集合。

在Go中接口包含两种含义: 它既是方法的集合, 同时还是一种类型. 在Go语言中是隐式实现的,意思就是对于一个具体的类型,不需要声明它实现了哪些接口,只需要提供接口所必需的方法。

在Go的类型系统中有一个核心概念: 我们不应该根据类型可以容纳哪种数据而是应该根据类型可以执行哪种操作来设计抽象类型。

如果一个具体类型实现了某个接口的所有方法, 我们则成为该具体类型实现了该接口。注意必须是所有方法。

值接收者和指针接收者

实现接口方法是值接收者,那变量传值或指针都可以,如果是指针接收者,则调用接口方法时需要传递指针,传值会编译错误。

原因就是在Go中所有的都是值传递, 尽管传入的是指针, 但是通过该指针我们可以找到其对应的值, Go语言隐式帮我们做了类型转换.我们记住在 Go语言中指针类型可以获得其关联的任意值类型, 但反过来却不行. 其实简单的想一下, 一个具体值可能有无数个指针指向它, 但一个指针只会指向一个具体的值。

类型断言

判断接口实际值的类型可以用类型断言:v, ok := x.(T),T是一个已知类型.

还一个需要注意的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
)

func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}
}

func main() {
names := []string{"stanley", "david", "oscar"}
PrintAll(names)
}

这段代码会编译错误,cannot use names (type []string) as type []interface {} in argument to PrintAll。如果想使其正常工作,我们必须将 []string 转为 []interface{}。

总结

  • 通过考虑数据类型之间的相同功能来创建抽象,而不是相同字段
  • interface{} 的值不是任意类型,而是 interface{} 类型
  • 接口包含两个字的大小,类似于 (type, value)
  • 函数可以接受 interface{} 作为参数,但最好不要返回 interface{}
  • 指针类型可以调用其所指向的值的方法,反过来不可以
  • 函数中的参数甚至接受者都是通过值传递
  • 一个接口的值就是就是接口而已,跟指针没什么关系
  • 如果你想在方法中修改指针所指向的值,使用 * 操作符

refence:

https://juejin.im/post/5a6931dc518825734501b591