简析go语言中组合
go语言的设计哲学是一切皆组合,通过组合实现类似“继承“的机制。组合方式主要有两种。垂直组合(类型组合):类型嵌入(type embedding),通过类型嵌入实现方法实现的复用、接口定义重用等;水平组合:以接口类型变量作为程序水平组合的连接点。
1.垂直组合——类型嵌入
类型嵌入主要有3中方法,接口中嵌入接口、结构体中嵌入接口及结构体中嵌入结构体。此处不做深入探究。
2.水平组合
以接口为连接点的水平组合方式可以将各个垂直组合出的类型耦合在一起,搭建出程序的基本框架。水平组合有以下几种惯用形式。
1.基本形式:水平组合的基本形式是接受接口类型参数的函数或方法
func FunctionName(param InterfaceType)
type I interface { M1() M2() } type T1 struct{} func (t T1) M1() { println("This is T1's M1") } func (t T1) M2() { println("This is T1's M2") } type T2 struct{} func (t T2) M1() { println("This is T2's M1") } func (t T2) M2() { println("This is T2's M2") } type T3 struct{} func (t T3) M1() { println("This is T3's M1") } func (t T3) M2() { println("This is T3's M2") } func BasicForm(param I) { param.M1() param.M2() } func main() { t1 := T1{} t2 := T2{} t3 := T3{} BasicForm(t1) BasicForm(t2) BasicForm(t3) }
通过上述简例可以看出,BasicForm函数的参数类型为接口类型,接受接口类型参数的BasicFrom函数作为连接点,将多种类型组织到一起,共同形成一幅程序”骨架“。
2.包裹函数:接受接口类型参数,并返回与其参数类型相同的返回值,即返回接口类型值。通过包裹函数可以实现对输入数据的过滤、装饰、变换等操作,并将结果再次返回给调用者
func WrapperFunction(param InterfaceType) InterfaceType
import "fmt" type Information interface { modify(n uint8) } type Person struct { name string age uint8 } func (p *Person) modify(age uint8) { p.age = age } func ModifyInformation(i Information, age uint8) Information { i.modify(age) return i } func main() { person := Person{ name: "John", age: 25, } ModifyInformation(&person, uint8(18)) fmt.Printf("%+v\n", person) } $ go run horizontal_combine.go {name:John age:18}
通过ModifyInformation函数包裹后,age字段发生了修改变化。
包裹函数的返回值类型和参数类型相同,因此可以将多个接受同一接口类型参数的包裹函数串联起来组合成一条链来调用。形式为:WrapperFuction1(WrapperFunction2(WrapperFunction3(...)))
3.适配器函数类型:适配器函数类型是一个辅助水平组合实现的”工具“类型,它是一个类型。可以将一个满足特定函数签名的普通函数显示转换成自身类型的实例,转换后的实例同时也是某个单方法接口类型的实现者。
Go语言学习笔记、语法知识、技术要点和个人理解及实战