Go学习笔记:Go的指针、interface

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

最近在使用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的指针,这个是没有意义的

转载于:https://my.oschina.net/coderzhoutf/blog/1614219

你可能感兴趣的:(Go学习笔记:Go的指针、interface)