go interface 的坑

一、概述

 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 code
11 package main
12 
13 import "fmt"
14 import "demo/lib"
15 
16 type MyPrint struct {         
17     name string               
18 }
19 
20 type Interface interface {
21     Print(string) error
22 }
23 
24 func (this *MyPrint) Print(who string) error {
25     fmt.Printf("%s name is %s
", who, this.name)
26     return nil
27 }
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
", 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         Values
2 -----------------------------------------------
3 (t T)                     T and *T
4 
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) error
12 }
13 
14 func (this *MyPrint) Print(who string) error {
15     fmt.Printf("%s name is %s
", 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
", 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) error
12 }
13 
14 func (this MyPrint) Print(who string) error {
15     fmt.Printf("%s name is %s
", 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
", 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) error
12 }
13 
14 func (this MyPrint) Print(who string) error {
15     fmt.Printf("%s name is %s
", 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
", MyInterface)
27     MyInterface.Print("my")
28 }
原文地址:https://www.cnblogs.com/chris-cp/p/7596089.html