golang中没有继承和多态,只支持封装,那些在C/C++/Java中使用继承和多态实现的方式,在golang中就可以使用接口来进行实现,golang的接口比其他语言就灵活很多。 如下就是一个使用接口的例子:

type Traversal interface {
    Traverse()
}
 
func main() {
    traversal := getTraversal()
    traversal.Traverse()
}

1. duck typing的概念

img

1.1 大黄鸭是鸭子吗?

  • 传统类型系统:脊索动物门,脊椎动物亚门,鸟纲雁形目… 不是
  • duck typing:是鸭子
  • duck typing概念:“像鸭子走路,像鸭子叫(长得像鸭子),那么就是鸭子”
  • duck typing描述事物的外部行为而非内部结构
  • 严格说 go 属于结构化类型系统,类似 duck typing, 不是动态绑定的,golang是编译期绑定的。

1.2 Python中的duck typing

def download(retriever):
    return retriever.get("www.baidu.com")
  • 运行时才知道传入的 retriever 有没有 get
  • 需要注释来说明接口

1.3 C++中的 duck typing

template <class R>
string download(const R& retriever) {
    return retriever.get("www.baidu.com")
}
  • 编译时才知道传入的 retriever 有没有 get, 编写代码的时候不知道
  • 需要注释来说明接口

1.4 Java 中的类似代码

<R extends Retriever>
String download(R r) {
    return r.get("www.baidu.com")
}
  • 不是 duck typing,只有类似的代码
  • 传入的参数必须实现 Retriever 接口, 这一点相比Python/C++
  • 同时需要 Readable, Appendable 怎么办?(apache polygene)(实现多个接口时就不灵活了)

1.5 Go 语言的 duck typing

  • 同时具有 Python, C++duck typing 的灵活性
  • 又具有 Java 的类型检查

2. 接口的定义和实现

2.1 接口的定义

使用者(download)→ 实现者(retriever)

  • 接口由使用者定义
type Retriever interface {
	Get(url string) string
}
 
func download(r Retriever) string {
	return r.Get("http://www.baidu.com")
}

2.2 接口的实现

  • 接口的实现是隐式的
  • 只要实现接口里的方法

3. 接口的值类型

3.1 接口变量

  • 实现者的类型
  • 实现者的值或实现者的指针

3.2 接口变量里面有什么

  • 接口变量自带指针
  • 接口变量同样采用值传递,几乎不需要使用接口的指针
  • 指针接收者实现只能以指针方式使用;值接收者都可

3.3 查看接口变量

  • 表示任何类型:interface{}
  • Type Assertion
  • Type Switch

4. 接口的组合

type ReaderWriter interface {
	Reader
	Writer
}

5. 常用系统接口

  • Stringer
  • Reader/Writer