关于Golang中range指针数据的坑详解
前言
在Golang中使用forrange语句进行迭代非常的便捷,但在涉及到指针时就得小心一点了。
下面的代码中定义了一个元素类型为*int的通道ch:
packagemain import( "fmt" ) funcmain(){ ch:=make(chan*int,5) //sender input:=[]int{1,2,3,4,5} gofunc(){ for_,v:=rangeinput{ ch<-&v } close(ch) }() //receiver forv:=rangech{ fmt.Println(*v) } }
在上面代码中,发送方将input数组发送给ch通道,接收方再从ch通道中接收数据,程序的预期输出应该是:
现在运行一下程序,得到的输出如下:
很明显,程序并没有达到预期的结果,那么问题出在哪里呢?我们将代码稍作修改:
//receiver forv:=rangech{ fmt.Println(v) }
得到如下输出:
0x416020
0x416020
0x416020
0x416020
0x416020
可以看到,5次输出变量v(*int)都指向了同一个地址,返回去检查一下发送部分代码:
for_,v:=rangeinput{ ch<-&v }
问题正是出在这里,在forrange语句中,v变量用于保存迭代input数组所得的值,但是v只被声明了一次,此后都是将迭代input出的值赋值给v,v变量的内存地址始终未变,这样再将v的地址发送给ch通道,发送的都是同一个地址,当然无法达到预期效果。
解决方案:
引入一个中间变量,每次迭代都重新声明一个变量temp,赋值后再将其地址发送给ch:
for_,v:=rangeinput{ temp:=v ch<-&temp }
抑或直接引用数据的内存(推荐,无需开辟新的内存空间):
fork,_:=rangeinput{ c<-&input[k] }
再次运行,就可看到预期的效果。以上方案是用于讨论range语句带来的问题,当然,平时还是尽量避免使用指针类型的通道。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。