Golang的水平組合思維(1)——interface wrapper function

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

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

//show/show.go
package show
type Shower interface {
    Show()
}

這是一個最簡單的,定義了一個Shower的接口并聲明了Show方法,滿足這個接口的類型Type.Show()將在屏幕顯示用戶定義的一段文字。
隨后我們需要為這個Shower接口添加一個實例。例如我們添加一個數據類型使他能夠顯示Demo:user-string

//demo/demo.go
package demo
type Show struct {
    s string
}
func (this *Show) Show(){
    fmt.Println("Demo:",this.s)
}

這段代碼是否應該屬于package show?不是,因為實現Show()方法不止這一種。例如我們還可以:

//demo2/demo.go
package demo2
type Show struct {
    s string
}
func (this *Show) Show(){
    fmt.Println("This is another Demo: ",this.s)
}

接下來我們可以在main.go中使用這個接口和對應的方法:

//main.go
package main
import(
    "show"
    "demo"
    "demo2"
)
func main(){
    var ds show.Shower = &demo.Show{"string from main"}
    var d2s show.Shower = &demo2.Show{"string from main"}
    ds.Show()
}

我們一般用一個函數來包裝參數,使之直接返回一個接口類型。這是interface warp function的其中一種用法:

//demo/demo.go
func NewShow(s string) show.Shower {return &Show{s}}
//demo.Show不是Shower接口的實現類型,*demo.Show才是

在main.go中使用這個方法來創建接口:

//main.go
ds := demo.NewShow("string from main")
ds.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:

//which package does it belong??
type ShowMutliTimes_s struct {
    n int  //n times
}
func (this *ShowMultiTimes_s) Show(){
    for i:=0;i<this.n;i++{
        //??
    }
}

可以發現,這個方法應該同時對所有Shower的實現類型生效。同時他打印的內容也與Shower的實現類型(如Demo,Demo2)有關,因此他應該是一個屬于package show的方法:

package show
import "fmt"

type ShowMultiTimes struct {
    S Shower
    n int
}
func (this *ShowMultiTimes) Show(){
    for i:=0;i<this.n;i++{
        fmt.Print("Time",i,": ")
        this.S.Show()
    }
}

我們說interface wrapper function的第二種用法,即接受interface類型參數,并返回與其參數類型相同的返回值。

func ShowNTimes(s Shower, n int) Shower {return &ShowMultiTimes{s,n}}

ShowNTimes是一個wrapper function,它在s的外面再包裹上ShowMultiTimes。通過wrapper function將NewShow和ShowMultiTimes 的兩者巧妙的組合在了一起。這樣當我們采用包裝后的Shower去Read時,輸出的是經過處理后的字符串了。

//main.go
package main
import(
    "show"
    "demo"
    "demo2"
)
func main(){
    st:=show.ShowNTimes(test.NewShowI("String from main"),3)
    st.Show()
}

可以看到,interface warp function可以組合成一個chain,因為其wrapper function返回值類型與parameter類型相同。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容