2019独角兽企业重金招聘Python工程师标准>>>
最近在使用Go的过程中,遇到了和指针相关的一些问题,经过整理,发现和我最开始理解的指针还不太一样。
问题一:在设计cache的时候,需要用到万能类型interface来装各种各样的键值对,有时候有些参数根据需要得使用指针类型,刚开始会这样写
func test(a *interface{}){
//do something here ...
}
会发现无论我传什么参数都会提示:
cannot use *mytype as type *interface
这个问题与下面其实是同一个问题。。。
问题二:有这么一个需求,定义了一个接口A,在另一个方法中,我想要设置一个参数是A的实现类型,因为这里会涉及到数据的修改,因此肯定是需要传一个指针。因此,想当然的写出了下面的代码
type myinterface interface{
print()
}
func test(value *myinterface){
//someting to do ...
}
刚开始觉得没有问题,但是!在调用test的时候遇到了问题。
type mystruct struct {
i int
}
//实现接口
func (this *mystruct) print(){
fmt.Println(this.i)
this.i=1
}
func main(){
m := &mystruct{0}
test(m)//错误
test(*m)//错误
}
*mystruct是实现了myinterface接口的,我希望test接收的是一个指针类型,因此传*mystruct类型的数据。提示:Cannot use 'm' (type *mystruct) as type *myinterface
说的很明确,无法将*mystruct类型的数据赋值给*myinterface。通过查找各种资料,发现在go语言中,接口本身就是引用类型,换句话说,接口类型本身就是一个指针。对于我的需求,其实test的参数只要是myinterface就可以了,只需要在传值的时候,传*mystruct类型(也只能传*mystruct类型)
使用下面的代码测试一下
//一个用于测试的接口
type myinterface interface{
print()
}
//*mystruct现了myinterface接口
type mystruct struct {
i int
}
type mystruct2 struct {
i int
}
/**
测试一下map类型的指针问题
*/
func main() {
//测试*mystruct实现效果
m := &mystruct{0}
fmt.Printf("address in main is %p\n", m)
method1(*m)//method1的参数是mystruct类型
m.print()//m的值并没有受到影响
method2(m)//method2的参数是接口类型
m.print()//m的值被修改了
//测试mystruct2实现效果
fmt.Println("##########")
m2 := &mystruct2{i:0}
fmt.Printf("initial address is %p\n",m2)
method3(*m2)
m2.print()
method2(m2)
m2.print()
}
func method1(m mystruct) {
fmt.Printf("address in method1 is %p\n", &m)
m.print()
}
func method2(m myinterface){
fmt.Printf("address in method2 is %p\n",m)
m.print()
}
func method3(m mystruct2){
fmt.Printf("address in method3 is %p\n",&m)
m.print()
}
func (this *mystruct) print(){
fmt.Println(this.i)
this.i=1
}
func (this mystruct2) print(){
fmt.Println(this.i)
this.i=2
}
运行结果如下:
address in main is 0xc42001c090
address in method1 is 0xc42001c098
0
0
address in method2 is 0xc42001c090
1
1
##########
initial address is 0xc42001c0b0
address in method3 is 0xc42001c0b8
0
0
address in method2 is 0xc42001c0b0
0
0
可以看到,使用method2的时候,地址与main函数中的地址是一样的,也就是说,当参数是myinterface的时候,传的是一个引用类型。
另外,mystruct2无论使用哪种方式都没有改变main函数中的值,这个是因为mystruct2的print函数。
func (this mystruct2) print()
这种声明其实是
func print(this mystruct2)
可以看出,在print函数中传的是值,而非地址,因此不会影响到外部函数。
在这个过程中看到过一位大神说的一句:永远不要使用指向interface的指针,这个是没有意义的