go語言中channel可以理解是乙個先進先出的佇列,通過管道進行通訊。
csp 模型:傳統的併發模型主要分為 actor 模型和 csp 模型,csp 模型全稱為 communicating sequential processes,csp 模型由併發執行實體(程序,執行緒或協程),和訊息通道組成,實體之間通過訊息通道傳送訊息進行通訊。和 actor 模型不同,csp 模型關注的是訊息傳送的載體,即通道,而不是傳送訊息的執行實體。
它的操作符是箭頭 <- 。
ch <- v // 傳送值v到channel ch中
v := <-ch // 從channel ch中接收資料,並將資料賦值給v
(箭頭的指向就是資料的流向)
就像 map 和 slice 資料型別一樣, channel必須先建立再使用:
ch := make(chan int)
channel型別的定義格式如下:
channeltype = ( "chan" | "chan" "<-" | "<-" "chan" ) elementtype .
它包括三種型別的定義。可選的<-代表channel的方向。如果沒有指定方向,那麼channel就是雙向的,既可以接收資料,也可以傳送資料。
使用make初始化channel,並且可以設定容量:chan t // 可以接收和傳送型別為 t 的資料
chan<- float64 // 只可以用來傳送 float64 型別的資料
<-chan int // 只可以用來接收 int 型別的資料
<-總是優先和最左邊的型別結合。(the <- operator associates with the leftmost chan possible)
chan<- chan int // 等價 chan<- (chan int)
chan<- <-chan int // 等價 chan<- (<-chan int)
<-chan <-chan int // 等價 <-chan (<-chan int)
chan (<-chan int)
make(chan int, 100)
容量(capacity)代表channel容納的最多的元素的數量,代表channel的快取的大小。
如果沒有設定容量,或者容量設定為0, 說明channel沒有快取,只有sender和receiver都準備好了後它們的通訊(communication)才會發生(blocking)。如果設定了快取,就有可能不發生阻塞, 只有buffer滿了後 send才會阻塞, 而只有快取空了後receive才會阻塞。乙個nil channel不會通訊。
可以通過內建的close方法可以關閉channel。
你可以在多個goroutine從/往 乙個channel 中 receive/send 資料, 不必考慮額外的同步措施。
channel可以作為乙個先入先出(fifo)的佇列,接收的資料和傳送的資料的順序是一致的。
channel的 receive支援 multi-valued assignment,如
v, ok := <-ch
它可以用來檢查channel是否已經被關閉了。
send語句
send語句用來往channel中傳送資料, 如ch <- 3。
它的定義如下:
sendstmt = channel 「<-」 expression .
channel = expression .
在通訊(communication)開始前channel和expression必選先求值出來(evaluated),比如下面的(3+4)先計算出7然後再傳送給channel。
send被執行前(proceed)通訊(communication)一直被阻塞著。如前所言,無快取的channel只有在receiver準備好後send才被執行。如果有快取,並且快取未滿,則send會被執行。c := make(chan int)
defer close(c)
go func() ()
i := <-c
fmt.println(i)
往乙個已經被close的channel中繼續傳送資料會導致run-time panic。
往nil channel中傳送資料會一致被阻塞著。
receive 操作符
<-ch用來從channel ch中接收資料,這個表示式會一直被block,直到有資料可以接收。
從乙個nil channel中接收資料會一直被block。
從乙個被close的channel中接收資料不會被阻塞,而是立即返回,接收完已傳送的資料後會返回元素型別的零值(zero value)。
如前所述,你可以使用乙個額外的返回引數來檢查channel是否關閉。
如果ok 是false,表明接收的x是產生的零值,這個channel被關閉了或者為空。x, ok := <-ch
x, ok = <-ch
var x, ok = <-ch
import "fmt"
func sum(s int, c chan int)
c <- sum // send sum to c
}func main()
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // receive from c
fmt.println(x, y, x+y)
}
Go併發控制 channel
雖然上次提過的sync控制併發很簡單,但是他有一定的侷限性,他也只能控制能過讓所有的goroutine在程式結束時完成,並不能干涉各個goroutine,下面我們介紹一種更好的方式,就是利用通道 首先先說用channel控制併發在程式結束之前完成 func main ch sum fmt.print...
go語言 channel特點
通道擁有阻塞機制 無緩衝區 有緩衝區同理。接收端在傳送端資料傳送完成之前 通道為nil 處於阻塞狀態 傳送端在接收端資料拿走完成之前 通道為滿 處於阻塞態 1.struct 型別不佔空間,作為通道的一種訊號方式 2.chan型別為引用型別,故需要進行初始化,申請空間,在通道使用結束後close 關閉...
go 通道 go語言通道channel
通過使用通道,在多個goroutine傳送和接受共享的資料,達到資料同步的目的。通道,他有點像在兩個routine之間架設的管道,乙個goroutine可以往這個管道裡塞資料,另外乙個可以從這個管道裡取資料,有點類似於我們說的佇列。宣告乙個通道很簡單,我們使用chan關鍵字即可,除此之外,還要指定通...