首页 > 编程语言 >Go语言精进之路读书笔记第29条——使用接口作为程序水平组合的连接点

Go语言精进之路读书笔记第29条——使用接口作为程序水平组合的连接点

时间:2024-02-19 22:01:08浏览次数:32  
标签:组合 读书笔记 29 接口 类型 接口类型 io Reader Go

如果说C++和Java是关于类型层次结构和类型分类的语言,那么Go则是关于组合的语言。 —— Rob Pike,Go语言之父

“偏好组合,正交解耦”

29.1 一切皆组合

在语言设计层面,Go提供了诸多正交的语法元素供后续组合使用,包括:

  • Go语言无类型体系(type hierarchy),类型定义独立;
  • 方法和类型是正交的,每种类型都可以拥有自己的方法集合;
  • 接口与其实现者之间无显式关联。

主要的两种组合方式:

  • 垂直组合(类型组合):通过类型嵌入机制实现垂直组合,进而实现方法实现的复用、接口定义重用
  • 水平组合:以接口类型变量作为程序水平组合的连接点

29.2 垂直组合回顾

Go语言通过类型的垂直组合而不是继承让单一类型承载更多的功能。调用方法时,方法的匹配取决于方法名称,而不是类型。

(1) 通过嵌入接口构建接口

// $GOROOT/src/io/io.go
type ReadWriter interface {
    Reader
    Writer
}

(2) 通过嵌入接口构建结构体

type MyReader struct {
    io.Reader   // 底层的reader
    N int64     // 剩余最大字节数
}

嵌入io.Reader的MyReader类型自然实现了io.Reader接口。可以用于快速构建满足某一接口的结构体类型,以满足单元测试的需要,而我们仅需实现少数需要的接口方法即可

(3) 通过嵌入结构体构建新结构体

// $GOROOT/src/sync/pool.go
type poolLocal struct {
    private interface{}
    shared  []interface{}
    Mutex
    pad     [128]byte
}

被嵌入Mutex的poolLocal“继承”了Mutex的Lock和Unlock实现,但实质上在结构体中嵌入接口类型名和在结构体中嵌入结构体,都是“委派模式”(delegate)的一种应用。

对新结构体类型的方法调用可能会被“委派”给该结构体内部嵌入的结构体的实例。

比如上面的poolLocal结构体,对于外部来说它拥有Lock和Unlock方法,但当Lock/Unlock方法被调用时,方法调用实际被传给了poolLocal中的Mutex实例。

29.3 以接口为连接点的水平组合

以接口为连接点的水平组合方式可以将各个垂直组合出的类型耦合在一起,从而编织出程序静态骨架。而通过接口进行水平组合的一种常见模式是使用接受接口类型参数的函数或方法。
以下是以接口为连接点的水平组合的几种惯用形式。

1.基本形式

水平组合的基本形式是接受接口类型参数的函数或方法,代码如下:

func YourFuncName(param YourInterfaceType)

函数/方法参数中的接口类型作为连接点,将位于多个包中的多个类型“编织”到一起,共同形成一幅程序“骨架”。

同时接口类型与其实现者之间隐式的关系在不经意间满足了依赖抽象、里氏替换原则、接口隔离等代码设计原则。

实例:

// $GOROOT/src/io/ioutil/ioutil.go
func readAll(r io.Reader, capacity int64) (b []byte, err error)

// $GOROOT/src/io/io.go
func Copy(dst Writer, src Reader) (written int64, err error)

2.包裹函数

包裹函数(wrapper function)的形式是这样的:它接受接口类型参数,并返回与其参数类型相同的返回值。其代码如下:

func YourWrapperFunc (param YourInterfaceType) YourInterfaceType

通过包裹函数可以实现对输入数据的过滤、装饰、变换等操作,并将结果再次返回给调用者。

// $GOROOT/src/io/io.go
func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n}}

type LimitedReader struct {
    R Reader
    N int64
}

func (l *LimitedReader) Read(p []byte) (n int, err error) {
    ...
}

由于包裹函数的返回值类型与参数类型相同,因此我们可以将多个接受同一接口类型参数的包裹函数组合成一条链来调用,其形式如下:

YourWrapperFunc1(YourWrapperFunc2(YourWrapperFunc3(...)))

3.适配器函数类型

适配器函数类型(adapter function type)是一个辅助水平组合实现的“工具”类型。强调一下,它是一个类型。

它可以将一个满足特定函数签名的普通函数显式转换成自身类型的实例,转换后的实例同时也是某个单方法接口类型的实现者。

最典型的适配器函数类型莫过于第21条提到过的http.HandlerFunc了。

// $GOROOT/src/net/http/server.go
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

4.中间件

在Go Web编程中,“中间件”常常指的是一个实现了http.HandlerFunc类型实例,如authHandler、loginHandler。实质上,这里的中间件就是包裹函数和适配器函数类型结合的产物。

标签:组合,读书笔记,29,接口,类型,接口类型,io,Reader,Go
From: https://www.cnblogs.com/brynchen/p/18022044

相关文章

  • 读书笔记3
    第三章软件工程师的成长这章主要讨论软件工程师个人能力衡量及发展,一些思维误区和以后的职业发展在团队工作中,稳定、一致的交付时间时衡量一个员工能力的重要方面初级软件工程师的成长包括以下几种:(1)积累软件开发相关的知识,提升技术技能(如对具体技术的掌握,动手能力)。例如:对JAV......
  • Goldendb安装部署
    目录一、概览1.1、文档用户1.2、术语1.3缩略语二、环境准备2.1安装准备2.1.1Redhat8.5系统的Python2.7安装方法2.2、修改主机名2.3、关闭防火墙和透明大页(所有节点)2.4配置yum,安装系统包2.5创建目录和安装pip三、一键安装使用步骤3.1root用户登录IP1服务器3.2执行如下命令,解......
  • 基于python+django+vue.js开发的学生成绩管理系统
    功能介绍平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。功能包括:成绩管理、学生管理、课程管理、班级管理、用户管理、日志管理、系统信息模块。源码地址https://github.com/geeeeeeeek/python_score演示地址http://score.gitapp.cn演示......
  • 基于python+django+vue.js开发的社区养老管理系统
    功能介绍平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。功能包括:老人管理、护工管理、亲属管理、病史管理、房间管理、活动管理、用户管理、日志管理、系统信息模块。源码地址https://github.com/geeeeeeeek/python_yanglao演示地址http:/......
  • 基于python+django+vue.js开发的健身房管理系统
    功能介绍平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。功能包括:教练管理、会员管理、场地管理、设备管理、用户管理、日志管理、系统信息模块。源码地址https://github.com/geeeeeeeek/python_fitness演示地址http://fitness.gitapp.cn......
  • 基于python+django+vue.js开发的停车管理系统
    功能介绍平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。功能包括:车位管理、会员管理、停车场管理、违规管理、用户管理、日志管理、系统信息模块。源码地址https://github.com/geeeeeeeek/python_parking演示地址http://parking.gitapp.cn......
  • 基于python+django+vue.js开发的医院门诊管理系统/医疗管理系统
    功能介绍平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。功能包括:医生管理、科室管理、护士管理、住院管理、药品管理、用户管理、日志管理、系统信息模块。源码地址https://github.com/geeeeeeeek/python_hospital演示地址http://hospital......
  • day29 回溯算法part5 代码随想录算法训练营 47. 全排列 II
    题目:47.全排列II我的感悟:用了一层判断,感觉也挺好用的理解难点:老师的写法,主要是理解used【i】和used[i-1]的概念我说怎么参考答案看不懂呢,它把两个判断放在一起写了。我的代码:用了一层判断classSolution:defpermuteUnique(self,nums:List[int])->List[Lis......
  • Go 日期时间包装器:15条更便捷的时间处理
    Go日期时间包装器:15条更便捷的时间处理原创 TimLiu 爱发白日梦的后端 2024-01-1907:02 广东 听全文爱发白日梦的后端专注Go语言领域的发展,学习成为更牛逼的架构师,日常分享Go语言、架构、软件工具的使用。169篇原创内容公众号点击上方“名片......
  • golang基本数据类型
    数据类型介绍Go语言中的数据类型分为:基本数据类型和复合数据类型基本数据类型:整型、浮点型、布尔型、字符串复合数据类型:数组、切片、结构体、函数、map、通道(channel)、接口等基本数据类型:整型整型分为两个大类:有符号整型按长度分为:int8、int16、int32、int6......