Channel - cruisechang/wiki-golang GitHub Wiki
Initial
//初始化一個具有5個buffer的channel。
c:=make(chan int,5)
//初始化沒有buffer的channel
c:=make(chan int)
Attribute
-
Channel是值類型(是指Channel本身,不是Channel裡面的元素)
-
Channel的功能是傳遞元素,不是儲存元素。
-
Channel裡的元素是有先後順序的。先進先出(FIFO)。
-
Channel裡的元素具有原子性。
-
Channel裡的元素只能被read一次,不會有兩個Goroutine read到相同元素。
-
元素一但被read,立刻就從channel中刪除。
-
Channel的buffer數量是固定的,一但初始化之後就不能更改。
Operation
-
Channel的操作本身是同步的。
-
不同Goroutine可以對同一個channel進行send,receive操作。
Send/Receive
c:=make(chan int,5)
//Send to c
c<-1
//Receive from c
x:=<-c
//或是接收第二個值,判斷receive是否成功。
//當channel被關閉時,ok=false,此時就可知道receive是失敗的,即便還是有取到資料。
//此時取到的資料不是正確的,是資料類型的0值。
x,ok:=<-c
ch:=make(chan int,3)
ch<-1
ch<-2
x:=<-ch
fmt.Println(x) //x=1
close(ch)
x,ok:=<-ch
fmt.Println(x,ok) //x=2,ok=true
x,ok=<-ch
fmt.Println(x,ok) //x=0 (int type zero value),ok=false
對no buffer channel 進行操作
如下範例,此時當前Goroutine會被block住,
直到有其他Goroutine對c這個channel進行read操作。
因為channel本身是個通道,並不是容器,且這個channel並未設定buffer,
所以不容許存放資料在channel裡,必須即時取走,所以在未被取走前,會block後續執行。
//No buffer chan
c:=make(chan int)
c<-1
Close Channel
ch:=make(chan int,5)
close(ch)
//對已經close channel 發送,產生panic
ch<-1
//再次close,產生panic
close(ch)
- 應在發送端進行close(),不應在接收端進行close()。避免發送端產生panic。
- 對已close的channel(或未初始化的channel)進行發送,會產生panic。
- close之後,接收端依舊可以接收channel裡剩餘的元素。
- close之後,接收端如果有用ok來判斷接收正確否,並不會立刻得到false,而是在接收完所有元素才會得到false。
傳址給channel/傳實體給channel的差異
-
傳址給channel,途中改變元素的值,後來取到的值 ->會改變
-
傳實體給channel,途中改變元素的值,後來取到的值 ->不會改變
func main() {
type Sct struct{
ID string
}
//傳址
s := &Sct{ID: "id"}
c := make(chan *Sct, 5)
oriID := s.ID
c <- s
s.ID = "new id"
rs := <-c
newID := rs.ID
fmt.Printf("傳址進入channel 途中改變變數值,初始後來不同 oriID: %s, newID :%s \n", oriID, newID)
//傳實體
s2 := Sct{ID: "id"}
c2 := make(chan Sct, 5)
oriID = s2.ID
c2 <- s2
s2.ID = "new id"
rs2 := <-c2
newID = rs2.ID
fmt.Printf("傳實體進入channel 途中改變變數值,初始與後會相同 oriID: %s, newID :%s \n", oriID, newID)
}