Golang關於channel傳遞引用引發的坑

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

 Time won't go back I won't turn back.

時光不會倒著走,我也不會再回頭。

 其實這個問題其實是出現在參考型別( 此處是slice )上, 這個是 slice 的資料結構,它很簡單,一個指向真實 array 地址的指標 ptr ,slice 的長度 len 和容量 cap 。

 結構圖解1

每次cap改變的時候指向array記憶體的指標都在變化, 在實際使用中,我們最好事先預期好一個cap,這樣在使用append的時候可以避免反覆重新分配記憶體複製之前的資料,減少不必要的效能消耗。

現在上執行個體,來看看坑所在:

package mainimport "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 <- datatime.Sleep(time.Second * 5)}

預測的運行結果:

bbbbbbbbbb

aaa

 

但是肯定是有坑的

前面新起了一個協程來等待通道接受資訊, 主進程繼續執行, 當data傳遞給了通道之後, 立刻修改了data指向數組的值(第二次append), 所以通道第一次接收的值就已經改變了, 因為我們傳遞的是引用,不是實值型別。

解決方案呢就是加鎖 或者新變數拷貝。

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.