使用chan的時候選擇對象還是指針


使用chan的時候選擇對象還是指針

今天在寫代碼的時候遇到一個問題,在創建一個通道的時候,不確定創建的通道是使用chan A還是chan *A。

思考了一下,覺得這個應該和函數一樣是一個值傳遞還是參數傳遞的問題。然后寫了個play驗證了一下。

package main


import (
	"fmt"
	"time"
)


type B struct {
       Value int
}

type A struct {
	Bv B
}


func main() {
  ch := make(chan *A)

	b := B{1}
	a := A{Bv:b}

	go func(ch chan *A){
	   for {
		select {
		case a := <-ch:
			a.Bv.Value = 2
		}
	    }
	}(ch)

	ch <- &a
	time.Sleep(2 * time.Second)
	fmt.Println(a)
}

這里a.Bv.Value的值改了。 但是如果我這里的ch是make(chan A)的話,則打印出來的值為1了。

事實證明確實是這樣。再去源碼里面看看。

chan的結構是在src/runtime/chan.go 的hchan。我們就看chan.go里面的recv方法

func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {

這個函數就是<-ch 的時候調用的。這里的c代表的就是我們使用的這個chan, ep代表的是ch傳輸出來的數據存儲的位置。

它在從channel中獲取數據的時候調用的是

recv(c, sg, ep, func() { unlock(&c.lock) }, 3)

看到這個函數里面,就可以看到使用的是typedmemmove 這個函數,這個函數就是c中的memmove。

將原先的數據,直接拷貝到目標內存中。所以這里說明channel是進行值拷貝的。

總結

基本上,chan的使用,如果是結構體的話,建議能使用指針就使用指針。

備注

本文golang代碼基於go1.11.4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM