本文视频地址
Java、C++ 等支流面向对象(以下简称 OO)语言通过简单和宏大的、自上而下的类型体系、继承、显式接口实现等机制将程序的各个局部耦合起来,但在 Go 语言中咱们找不到经典 OO 的语法元素、类型体系和继承机制,或者说 Go 语言实质上就不属于经典 OO 语言领域。针对这种状况,很多人会问:那 Go 语言是如何将程序的各个局部有机地耦合在一起的呢?Go 语言听从的设计哲学也是组合。
在介绍组合之前,咱们能够先来理解一下 Go 在语法元素设计时是如何为组合哲学的利用打下坚实基础的。
在 Go 语言设计层面,Go 设计者为 gopher 们提供了语法元素供后续组合应用,包含:
- Go 语言无类型体系(type hierarchy),类型之间是独立的,没有子类型的概念;
- 每个类型都能够有本人的办法汇合,类型定义与办法实现是正交独立的;
- 接口 (interface) 与其实现之间 ” 隐式关联 ”;
- 包 (package) 之间是绝对独立的,没有子包的概念。
咱们看到无论是包、接口还是一个个具体的类型定义 (包含类型的办法汇合),Go 语言为咱们出现了这样的一幅图景:一个个没有关联的积木,但每个积木又都很精彩。当初摆在面前的工作就是在这些积木之间以最适当的形式建设关联(耦合),造成一个 ” 整体 ”。Go 采纳了组合的形式,也是惟一的形式。
Go 语言提供了的最为直观的组合的语法元素就是 type embedding,即类型嵌入。通过类型嵌入,咱们能够将曾经实现的性能嵌入到新类型中,以疾速满足新类型的性能需要,这种形式有些相似经典 OO 的“继承”,但在原理上与经典 OO 的继承齐全不同。这是一种 Go 精心设计的“语法糖”,被嵌入的类型和新类型两者之间没有任何关系,甚至互相齐全不晓得对方的存在,更没有经典 OO 那种父类、子类的关系以及向上、向下转型(type casting)。通过新类型实例调用办法时,办法的匹配取决于办法名字,而不是类型。这种组合形式,我称之为“垂直组合”,即通过类型嵌入,疾速让一个新类型“复用”其余类型曾经实现的能力,实现性能的垂直扩大。
上面是一个类型嵌入的例子:
Go 规范库:sync/pool.go
type poolLocal struct {
...
Mutex // Protects shared.
...
}
咱们在 poolLocal 这个 struct 中嵌入类型 Mutex,被嵌入的 Mutex 类型的办法汇合会被晋升到里面的类型中。比方,这里的 poolLocal 将领有 Mutex 类型的 Lock 和 Unlock 办法。理论调用时,办法调用理论会被传给 poolLocal 中的 Mutex 实例。
咱们在规范库中还常常看到相似如下的 interface 类型嵌入的代码:
type ReadWriter interface {
Reader
Writer
}
通过在 interface 中嵌入 interface type,实现接口行为的聚合,组成大接口,这种形式在规范库中很常见,曾经成为了 Go 语言的一种常见的用法。
interface 是 Go 语言中真正的魔法,是 Go 语言的一个翻新设计,它只是办法汇合,并且它与实现者之间的关系是隐式的,它让程序外部各局部之间的耦合降至最低,同时它也是连贯程序各个局部之间“纽带”。隐式的 interface 实现会不经意间满足:依赖形象、里氏替换、接口隔离等准则,这在其余语言中是须要很 ” 刻意 ” 的设计筹划能力实现的,但在 Go interface 来看,所有却是自然而然的。
通过 interface 将程序外部各个局部组合在一起的办法,我这里称之为程度组合。程度组合的“模式”很多,比方:一种常见办法就是:通过承受 interface 类型参数的一般函数进行组合,例如上面代码。
func ReadAll(r io.Reader) ([]byte, error)
func Copy(dst Writer, src Reader) (written int64, err error)
ReadAll 通过 io.Reader 这个接口将 io.Reader 的实现与 ReadAll 所在的包低耦合的程度组合在一起了。相似的程度组合“模式”还有 wrapper、middleware 等。
此外,Go 语言内置的并发能力也能够通过组合的形式实现“对计算能力的串联”,比方:通过 goroutine+channel 的组合实现相似 Unix Pipe 的能力。
至此,组合准则的利用展现了 Go 程序的骨架构造。类型嵌入为类型提供的垂直扩大能力,interface 是程度组合的要害,它好比程序肌体上的“关节”,给予连贯“关节”的两个局部各自“自在流动”的能力,而整体上又实现了某种性能。组合也让遵循“简略”准则的 Go 语言的表现力丝毫不逊色于其余简单的支流编程语言。