Go语言for range遍历通道传指针异常及优化方案问询
Go语言for range变量地址复用问题解答
一、地址复用的原因及文档说明
Go语言的for range循环中,迭代变量(比如示例里的packet)会被复用:整个循环周期内只会创建一次该变量,每次迭代只是将通道中的值覆盖到这个变量的内存空间里,而不是重新声明新变量。所以每次发送的&packet都是同一个内存地址,后续迭代会修改该地址指向的内容,导致读取指针时出现重复值。
这是Go语言的规范行为,官方文档在For语句章节明确说明:
The iteration variables may be declared by the "range" clause using a form of short variable declaration (:=). In this case their types are set to the types of the respective iteration values and their scope is the block of the "for" statement; they are re-used in each iteration.
二、更优雅的解决方案
不需要用for+select,有两种简洁的处理方式:
1. 循环内创建新变量保存当前值
在每次迭代中声明新变量,让指针指向新的内存地址:
for packet := range from { p := packet // 每次迭代生成新变量,分配独立内存 to <- &p } close(to)
2. 直接传递指针类型(原通道支持时)
如果from通道本身传递的是指针类型,直接转发即可,无需额外处理:
// 假设from是 chan *YourType for packet := range from { to <- packet } close(to)
另外你的v2代码之所以正常,是因为packet是在select的case分支内声明的,每次进入case都会创建新变量,地址不会复用——本质和第一种解决方案逻辑一致。
内容的提问来源于stack exchange,提问作者Hannes Lüer
相关产品推荐
相关产品推荐

