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.

一、概述

 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\n", who, this.name)
26     return nil
27 }
28 
29 func MyselfPrint(name string) Interface {
30     return MyPrint{name: name}
31 }
32 
33 func main() {
34     fmt.Println("Hi, " + lib.World())
35     MyInterface := MyselfPrint("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         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\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 }

或者:

 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\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 }
 再或者:
 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\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 }

 

相关文章
|
1月前
|
Go
|
4月前
|
Go
go interface 使用
go interface 使用
28 0
|
6月前
|
Go
Go语言学习之 interface
Go语言学习之 interface
17 0
|
8月前
|
Go
go的interface怎么实现的?
面试题:go的interface怎么实现的?
60 0
|
9月前
|
存储 缓存 Go
如何用好 Go interface
The bigger the interface, the weaker the abstraction.
65 0
|
9月前
|
Go
Go Interface 合法验证
- 值方法集和接口匹配 - 给接口变量赋值的不管是值还是指针对象,都ok,因为都包含值方法集 - 指针方法集和接口匹配 - 只能将指针对象赋值给接口变量,因为只有指针方法集和接口匹配 - 如果将值对象赋值给接口变量,会在编译期报错(会触发接口合理性检查机制)
|
Go Android开发 Python
实证与虚无,抽象和具象,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang接口(interface)的使用EP08
看到接口这两个字,我们一定会联想到面向接口编程。说白了就是接口指定执行对象的具体行为,也就是接口表示让执行对象具体应该做什么,所以,普遍意义上讲,接口是抽象的,而实际执行行为,则是具象的。
实证与虚无,抽象和具象,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang接口(interface)的使用EP08
|
存储 Java Go
速学Go语言接口interface
速学Go语言接口interface
|
Go
go语言map[string]string 转map[string]interface{}
go语言map[string]string 转map[string]interface{}
592 0
|
存储 Java Go
go的interface
go的interface
58 0