一、概述
1 [root@node175 demo]# tree 2 . 3 ├── lib 4 │ └── world.go 5 ├── README 6 └── server.go 7 8 1 directory, 3 files 9 10 #server.go code11 package main12 13 import "fmt"14 import "demo/lib"15 16 type MyPrint struct { 17 name string 18 }19 20 type Interface interface {21 Print(string) error22 }23 24 func (this *MyPrint) Print(who string) error {25 fmt.Printf("%s name is %s\n", who, this.name)26 return nil27 }28 29 func NewMyPrint(name string) Interface {30 return MyPrint{name: name}31 }32 33 func main() {34 fmt.Println("Hi, " + lib.World())35 MyInterface := NewMyPrint("bob")36 fmt.Printf("MyInterface type: %T\n", MyInterface)37 MyInterface.Print("my")38 }
运行:
[root@node175 demo]# go run server.go
# command-line-arguments./server.go:20: cannot use MyPrint literal (type MyPrint) as type Interface in return argument: MyPrint does not implement Interface (Print method has pointer receiver)为了解决这个问题,首先得先了解一下Golang 中 方法的集合的概念,一个struct虽然可以通过值类型和引用类型两种方式定义方法,但是不同的对象类型对应了不同的方法集:
Values Methods Receivers----------------------------------------------- T (t T)*T (t T) and (t *T)
值类型的对象只有(t T) 结构的方法,虽然值类型的对象也可以调用(t *T) 方法,但这实际上是Golang编译器自动转化成了&t的形式来调用方法,并不是表明值类型的对象拥有该方法。
换一个维度来看上面的表格可能更加直观:
1 Methods Receivers Values2 -----------------------------------------------3 (t T) T and *T4 5 (t *T) *T
这就意味着指针类型的receiver 方法实现接口时,只有指针类型的对象实现了该接口。
对应上面的例子来说,只有&MyPrint实现了Interface接口,而MyPrint根本没有实现该接口。所以上面代码会报出这样的异常。
1 MyPrint method has pointer receiver
解决这个问题也很容易,直接使用&MyPrint去代替MyPrint调用方法即可:
1 package main 2 3 import "fmt" 4 import "demo/lib" 5 6 type MyPrint struct { 7 name string 8 } 9 10 type Interface interface {11 Print(string) error12 }13 14 func (this *MyPrint) Print(who string) error {15 fmt.Printf("%s name is %s\n", who, this.name)16 return nil17 }18 19 func MyselfPrint(name string) Interface { 20 return &MyPrint{name: name}21 }22 23 func main() {24 fmt.Println("Hi, " + lib.World())25 MyInterface := MyselfPrint("bob")26 fmt.Printf("MyInterface type: %T\n", MyInterface)27 MyInterface.Print("my")28 }
或者:
1 package main 2 3 import "fmt" 4 import "demo/lib" 5 6 type MyPrint struct { 7 name string 8 } 9 10 type Interface interface {11 Print(string) error12 }13 14 func (this MyPrint) Print(who string) error {15 fmt.Printf("%s name is %s\n", who, this.name)16 return nil17 }18 19 func MyselfPrint(name string) Interface { 20 return MyPrint{name: name}21 }22 23 func main() {24 fmt.Println("Hi, " + lib.World())25 MyInterface := MyselfPrint("bob")26 fmt.Printf("MyInterface type: %T\n", MyInterface)27 MyInterface.Print("my")28 }
再或者:
1 package main 2 3 import "fmt" 4 import "demo/lib" 5 6 type MyPrint struct { 7 name string 8 } 9 10 type Interface interface {11 Print(string) error12 }13 14 func (this MyPrint) Print(who string) error {15 fmt.Printf("%s name is %s\n", who, this.name)16 return nil 17 }18 19 func MyselfPrint(name string) Interface {20 return &MyPrint{name: name}21 }22 23 func main() {24 fmt.Println("Hi, " + lib.World())25 MyInterface := MyselfPrint("bob")26 fmt.Printf("MyInterface type: %T\n", MyInterface)27 MyInterface.Print("my")28 }