2019独角兽企业重金招聘Python工程师标准>>>
Go不是面向对象的,因此在实现接口的方式上也没有implements关键字,而是通过实现接口(interface)所定义的方法,就表示某个结构体实现了该接口。
也正是因为Go不是面向对象的,Go中的结构体和类还有一点不同。Java中的类是包含有属性和方法的,在Go中,struct只定义了属性,方法是通过方法的接收者绑定到相应的结构体上的。
func (my myimplements) methoda(){
fmt.Println("methoda")
}
这段代码就是将methoda方法绑定到myimplements结构体上,使得myimplements可以拥有methoda方法。
看似比较简单,但是在实际过程中遇到了一个坑,就是方法的接收者。上面的例子中方法的接收者是一个值类型
func (my *myimplements) methoda(){
fmt.Println("methoda")
}
如果这样写,方法的接收者就是一个指针类型了。Go指南中对于这部分有一个简单的case,但是只说明了使用指针类型可以改变原对象的值,使用值类型是不能改变的。这个区别其实就是传值与传地址的区别,很好理解。
我想说的坑是在实现接口过程中,方法接收者类型所带来的问题。
package main
import "fmt"
/**
整理了一下最近在接口和指针方面遇到的问题
*/
type myinterface interface{
methoda()
methodb()
}
type myimplements struct {
}
func (my *myimplements) methoda(){
fmt.Println("methoda")
}
func (my *myimplements) methodb(){
fmt.Println("methodb")
}
func main(){
var my myinterface
//my=myimplements{}
/**
my=myimplements{}会报如下的错误:
cannot use myimplements literal (type myimplements) as type myinterface in assignment:
myimplements does not implement myinterface (methoda method has pointer receiver)
*/
my = &myimplements{}
/**
这样是可以通过编译的。而如果将myimplements中的两个方法methoda和methodb改为接收值,
第一种写法是可以通过编译的。
*/
}
上面的例子定义了一个接口myinterface和它的实现myimplements,在main函数中定义了一个变量my类型是接口类型,当我使用my=myimplements{}进行赋值时,会出现编译错误。
cannot use myimplements literal (type myimplements) as type myinterface in assignment:
myimplements does not implement myinterface (methoda method has pointer receiver)
大致意思是说我的myimplements没有实现myinterface接口。
这个错的根源在于我methoda方法的接收者是*myimplements,是myimplments的指针类型,Go会认为methoda方法绑定在了*myimplements上,而不是myimplements,因此我的myimplements并没有实现接口,实现接口的是*myimplements这个指针类型。
因此如果我还想继续使用指针作为方法的接收者,就需要将myimplements的指针赋值给my就可以通过编译了。
这个例子其实在Go指南中有提到过,不过那一节的重点是在介绍接口,当时没有留意,现在返回去再看的时候才发现