This is a creation in Article, where the information may have evolved or changed.
Background
Suppose we want to develop a producer-consumer model of code, a routine responsible for production data, a routine responsible for consumption data, the code is as follows:
Error code
type MsgStru struct { msg []int}var msgChan chan MsgStrufunc sendMsg() { buf := make([]int, 10) for i := 0; i < 10; i++ { buf[0] = i tmp := MsgStru{msg: buf[:1]} fmt.Printf("send:%+v\n", tmp) msgChan <- tmp } fmt.Println("finish send")}func recvMsg() { for { tmp, _ := <-msgChan fmt.Printf("recv:%+v\n", tmp) }}func main() { msgChan = make(chan MsgStru, 10) go sendMsg() time.Sleep(1 * time.Second) recvMsg()}
The expected output should be 0 to 9 in order, but actually print?
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 sendrecv:{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]}
The data received is the number 9, which is why?
Cause analysis
First look at the type representation of the data in the channel:
type MsgStru struct { msg []int}
MSG is a slice,slice in Go is a pointer plus length, which means that the incoming channel is a pointer to buf, BUF is a global variable, so the Channel 10 msg data is a pointer to the BUF, when recvmsg ready to read the data, The data in the BUF now becomes 9, so 10 msg read from the channel is 9.
Modify Scenario 1
Change global slice to local 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:%+v\n", tmp) msgChan <- tmp } fmt.Println("finish send")}
Results
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 sendrecv:{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]}
Modify Scenario 2
Change Slice to array
type MsgStru struct { msg [2]int}var msgChan chan MsgStrufunc sendMsg() { var buf [2]int for i := 0; i < 10; i++ { buf[0] = i tmp := MsgStru{msg: buf} fmt.Printf("send:%+v\n", tmp) msgChan <- tmp } fmt.Println("finish send")}
Results
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 sendrecv:{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]}
Postscript
has been in the csdn to write articles, the latter will be gradually converted to the book, but also ask you to support a lot.