3typeShow struct{

4s string

5}

6func(this *Show)Show(){

7fmt.Println( "This is another Demo: ",this.s)

8}

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

1//main.go

2packagemain

3import(

4"show"

5"demo"

6"demo2"

7)

8funcmain(){

9vards show.Shower = &demo.Show{ "string from main"}

10vard2s show.Shower = &demo2.Show{ "string from main"}

11ds.Show()

12}

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

1//demo/demo.go

2funcNewShow(s string)show.Shower{ return&Show{s}}

3//demo.Show不是Shower接口的实现类型,*demo.Show才是

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

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:

1//which package does it belong??

2typeShowMutliTimes_s struct{

3n int//n times

4}

5func(this *ShowMultiTimes_s)Show(){

6fori:= 0;i<this.n;i++{

7//??

8}

9}

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

1packageshow

2import"fmt"

3

4typeShowMultiTimes struct{

5S Shower

6n int

7}

8func(this *ShowMultiTimes)Show(){

9fori:= 0;i<this.n;i++{

10fmt.Print( "Time",i, ": ")

11this.S.Show()

12}

13}

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

1funcShowNTimes(s Shower, n int)Shower{ return&ShowMultiTimes{s,n}}

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

1//main.go

2packagemain

3import(

4"show"

5"demo"

6"demo2"

7)

8funcmain(){

9st:=show.ShowNTimes(test.NewShowI( "String from main"), 3)

10st.Show()

11}

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

ID:Golangweb