golang通道中传递slice数据的入坑经验
发布时间:2020-12-16 19:10:45 所属栏目:大数据 来源:网络整理
导读:背景 错误代码 原因分析 修改方案1 修改方案2 背景 假设我们要开发生产者-消费者模型的代码,一个routine负责生产数据,一个routine负责消费数据,具体代码如下: 错误代码 type MsgStru struct { msg [] int } var msgChan chan MsgStru func sendMsg() { b
背景假设我们要开发生产者-消费者模型的代码,一个routine负责生产数据,一个routine负责消费数据,具体代码如下: 错误代码type MsgStru struct {
msg []int
}
var msgChan chan MsgStru
func sendMsg() {
buf := make([]int, 10)
for i := 0; i < 10; i++ {
buf[0] = i
tmp := MsgStru{msg: buf[:1]}
fmt.Printf("send:%+vn",tmp)
msgChan <- tmp
}
fmt.Println("finish send")
}
func recvMsg() {
for {
tmp,_ := <-msgChan
fmt.Printf("recv:%+vn",tmp)
}
}
func main() {
msgChan = make(chan MsgStru, 10)
go sendMsg()
time.Sleep(1 * time.Second)
recvMsg()
}
期望的输出应该是顺序打印0到9,但是实际打印呢? send:{msg:[0]}
send:{msg:[1]}
send:{msg:[2]}
send:{msg:[3]}
send:{msg:[4]}
send:{msg:[5]}
send:{msg:[6]}
send:{msg:[7]}
send:{msg:[8]}
send:{msg:[9]}
finish send
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
recv:{msg:[9]}
接受到的数据都是数字9,这是为什么呢? 原因分析首先看通道中数据的类型表示: type MsgStru struct { msg []int }
msg是一个slice,slice在go中是一个指针加长度,也就是说传入到通道中的是指向buf的指针,buf是一个全局变量,所以通道中的10个msg的数据都是指向buf的指针,当recvMsg准备读取数据的时候,buf中的数据此时变为了9,所以从通道中读取的10个msg都是9. 修改方案1将全局slice改为局部slice func sendMsg() {
buf := make([]int,10)
for i := 0; i < 10; i++ {
buf[0] = i
tmpMsg := make([]int,0)
tmpMsg = append(tmpMsg,buf[:1]...)
tmp := MsgStru{msg: tmpMsg}
fmt.Printf("send:%+vn",tmp)
msgChan <- tmp
}
fmt.Println("finish send")
}
结果 send:{msg:[0]}
send:{msg:[1]}
send:{msg:[2]}
send:{msg:[3]}
send:{msg:[4]}
send:{msg:[5]}
send:{msg:[6]}
send:{msg:[7]}
send:{msg:[8]}
send:{msg:[9]}
finish send
recv:{msg:[0]}
recv:{msg:[1]}
recv:{msg:[2]}
recv:{msg:[3]}
recv:{msg:[4]}
recv:{msg:[5]}
recv:{msg:[6]}
recv:{msg:[7]}
recv:{msg:[8]}
recv:{msg:[9]}
修改方案2将slice 改为array type MsgStru struct {
msg [2]int
}
var msgChan chan MsgStru
func sendMsg() {
var buf [2]int
for i := 0; i < 10; i++ {
buf[0] = i
tmp := MsgStru{msg: buf}
fmt.Printf("send:%+vn",tmp)
msgChan <- tmp
}
fmt.Println("finish send")
}
结果 send:{msg:[0 0]}
send:{msg:[1 0]}
send:{msg:[2 0]}
send:{msg:[3 0]}
send:{msg:[4 0]}
send:{msg:[5 0]}
send:{msg:[6 0]}
send:{msg:[7 0]}
send:{msg:[8 0]}
send:{msg:[9 0]}
finish send
recv:{msg:[0 0]}
recv:{msg:[1 0]}
recv:{msg:[2 0]}
recv:{msg:[3 0]}
recv:{msg:[4 0]}
recv:{msg:[5 0]}
recv:{msg:[6 0]}
recv:{msg:[7 0]}
recv:{msg:[8 0]}
recv:{msg:[9 0]}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |