Time won't go back I won't turn back.数组
时光不会倒着走,我也不会再回头。数据结构
其实应该理解为是slice的坑致使。 app
这个问题实际上是出如今引用类型( 此处是slice )上, 这个是 slice 的数据结构,它很简单,一个指向真实 array 地址的指针 ptr ,slice 的长度 len 和容量 cap 。性能
结构图解1指针
每次cap改变的时候指向array内存的指针都在变化, 在实际使用中,咱们最好事先预期好一个cap,这样在使用append的时候能够避免反复从新分配内存复制以前的数据,减小没必要要的性能消耗。code
如今上实例,来看看坑所在:协程
package main import "fmt" import "time" func main() { ch := make(chan []byte, 10) go func() { for { select { case data := <-ch: fmt.Println(string(data)) } } }() data := make([]byte, 0, 32) data = append(data, []byte("bbbbbbbbbb")...) ch <- data // fmt.Printf("%p\n", data) data = data[:0] // fmt.Printf("%p\n", data) data = append(data, []byte("aaa")...) ch <- data time.Sleep(time.Second * 5) }
预测的运行结果:进程
bbbbbbbbbb内存
aaastring
可是确定是有坑的:
前面新起了一个协程来等待通道接受信息, 主进程继续执行, 当data第一次传递给了通道以后, (第二次append)马上修改了data指向数组的值(aaabbbbbbb),要注意的地方还有data = data[:0], 因此通道第一次接收的值就已经改变了, 由于咱们传递的是引用,不是值类型。
若是在Append以前sleep, 那么确定输出的是bbbbbb 。
解决方案呢就是加锁 或者新变量拷贝。