前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang的水平组合思维(1)——interface wrapper function

Golang的水平组合思维(1)——interface wrapper function

作者头像
李海彬
发布2019-05-08 11:36:56
1.2K0
发布2019-05-08 11:36:56
举报
文章被收录于专栏:Golang语言社区Golang语言社区

作者:Ovenvan 来源:简书

什么是Golang的正交组合-水平组合思维:Tony Bai的博客 - Coding in GO way - Orthogonal Composition

这篇文章研究其中提到的 interface wrapper function。

代码语言:javascript
复制
1//show/show.go
2package show
3type Shower interface {
4    Show()
5}

这是一个最简单的,定义了一个Shower的接口并声明了Show方法,满足这个接口的类型 Type.Show() 将在屏幕显示用户定义的一段文字。 随后我们需要为这个Shower接口添加一个实例。例如我们添加一个数据类型使他能够显示 Demo:user-string

代码语言:javascript
复制
1//demo/demo.go
2package demo
3type Show struct {
4    s string
5}
6func (this *Show) Show(){
7    fmt.Println("Demo:",this.s)
8}

这段代码是否应该属于 package show ?不是,因为实现Show()方法不止这一种。例如我们还可以:

代码语言:javascript
复制
1//demo2/demo.go
2package demo2
3type Show struct {
4    s string
5}
6func (this *Show) Show(){
7    fmt.Println("This is another Demo: ",this.s)
8}

接下来我们可以在main.go中使用这个接口和对应的方法:

代码语言:javascript
复制
 1//main.go
 2package main
 3import(
 4    "show"
 5    "demo"
 6    "demo2"
 7)
 8func main(){
 9    var ds show.Shower = &demo.Show{"string from main"}
10    var d2s show.Shower = &demo2.Show{"string from main"}
11    ds.Show()
12}

我们一般用一个函数来包装参数,使之直接返回一个接口类型。这是interface warp function的其中一种用法:

代码语言:javascript
复制
1//demo/demo.go
2func NewShow(s string) show.Shower {return &Show{s}}
3//demo.Show不是Shower接口的实现类型,*demo.Show才是

在main.go中使用这个方法来创建接口:

代码语言:javascript
复制
1//main.go
2ds := demo.NewShow("string from main")
3ds.Show()

注意在写interface warp的时候返回类型必须是接口类型,即 func NewShow(s string) Show {return &Show{s}} 或 func NewShow(s string) *Show {return &Show{s}} 都是错误的。虽说他们或许可以成功执行 ds.Show() 操作,但他们都只是一个结构体,也就是执行 ds.(show.Shower) 类型断言时编译器会抛出错误。

以上都是很基础的部分。接下来我们考虑一个需求,即我们需要用一个方法(接口)来实现将字符串连续打印多遍的功能。例如在stl中 LimitedReader 的实现方法。为此,我们创建一个结构体ShowMultiTimes并继承Shower:

代码语言:javascript
复制
1//which package does it belong??
2type ShowMutliTimes_s struct {
3    n int  //n times
4}
5func (this *ShowMultiTimes_s) Show(){
6    for i:=0;i<this.n;i++{
7        //??
8    }
9}

可以发现,这个方法应该同时对所有Shower的实现类型生效。同时他打印的内容也与Shower的实现类型(如Demo,Demo2)有关,因此他应该是一个属于package show的方法:

代码语言:javascript
复制
 1package show
 2import "fmt"
 3
 4type ShowMultiTimes struct {
 5    S Shower
 6    n int
 7}
 8func (this *ShowMultiTimes) Show(){
 9    for i:=0;i<this.n;i++{
10        fmt.Print("Time",i,": ")
11        this.S.Show()
12    }
13}

我们说interface wrapper function的第二种用法,即接受interface类型参数,并返回与其参数类型相同的返回值。

代码语言:javascript
复制
1func ShowNTimes(s Shower, n int) Shower {return &ShowMultiTimes{s,n}}

ShowNTimes是一个wrapper function,它在s的外面再包裹上ShowMultiTimes。通过wrapper function将NewShow和ShowMultiTimes 的两者巧妙的组合在了一起。这样当我们采用包装后的Shower去Read时,输出的是经过处理后的字符串了。

代码语言:javascript
复制
 1//main.go
 2package main
 3import(
 4    "show"
 5    "demo"
 6    "demo2"
 7)
 8func main(){
 9    st:=show.ShowNTimes(test.NewShowI("String from main"),3)
10    st.Show()
11}

可以看到,interface warp function可以组合成一个chain,因为其wrapper function返回值类型与parameter类型相同。


版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档