php小編小新在go語言中,通道是一種用于在goroutine之間傳遞數(shù)據(jù)的機制。通道的行為取決于消息發(fā)送到它的方式。當(dāng)通道被聲明為有緩沖的時候,發(fā)送消息的goroutine會將消息放入通道的緩沖區(qū),然后繼續(xù)執(zhí)行。而當(dāng)通道被聲明為無緩沖的時候,發(fā)送消息的goroutine會阻塞,直到有其他goroutine從通道中接收消息。因此,可以說通道的行為會根據(jù)消息發(fā)送到它的方式而改變。
問題內(nèi)容
為什么這兩段代碼的執(zhí)行方式不同?
-
運行以下代碼會返回
fatal 錯誤:所有 goroutine 都在休眠 - 死鎖!
error。
func main() { ch := make(chan int) ch <- 1 fmt.println(<-ch) }
登錄后復(fù)制
-
正確運行以下代碼會返回 2 和 3(各占一行)。
ch := make(chan int) go buffer(ch) fmt.Println(<-ch) fmt.Println(<-ch) } func buffer(ch chan int) { ch <- 2 ch <- 3 }
登錄后復(fù)制
僅當(dāng) ch 被定義為緩沖通道時,#1 才能正確執(zhí)行。為什么?為什么 buffer() 中的 ch 接受 2 個值而不抱怨?
解決方法
對無緩沖通道的發(fā)送操作將阻塞,直到另一個 goroutine 從中讀取數(shù)據(jù)。這就是第一段代碼死鎖的原因:當(dāng)您發(fā)送到通道時,沒有其他 goroutine 從中讀取。
在第二種情況下,您有一個 goroutine 向通道發(fā)送兩個值,并且主 goroutine 在發(fā)送的同時從通道讀取兩次。該通道不接受兩次發(fā)送,而是一個接一個地進行,第一個發(fā)送操作由第一次讀取解除阻塞,第二個發(fā)送操作由第二次讀取解除阻塞。