向一個goroutine通信
向通道發(fā)送一次消息只有一個goroutine能收到數(shù)據(jù)音婶,goroutine向一個通道取數(shù)據(jù)類似于銀行里一個柜臺排隊取錢棒拂,goroutine是那排在長長的隊伍,一個通道(channel)就是一個柜臺写隶,只有等前一個goroutine取完數(shù)據(jù)之后关顷,后一個goroutine才能取下一個數(shù)據(jù)缺菌。
-
一個goroutine循環(huán)接收
golang中向一個goroutine只需將值傳入通道中蚌斩,然后在goroutine里從這個通道取值即可荆忍,由于只有一個goroutine在循環(huán)接收數(shù)據(jù)匹耕,相當(dāng)于隊伍中只有一個人膜蛔,取完數(shù)據(jù)之后可以繼續(xù)站在柜臺前等待螟深,例如:
package main
import (
"bufio"
"os"
)
func main() {
ch, scan:= make(chan string),bufio.NewScanner(os.Stdin)
// goroutine1
go func() {
for {
fmt.Println(<-ch)
fmt.Println("goroutine1")
}
}()
// 按一次回車向通道發(fā)送一條消息
for {
scan.Scan()
ch <- "Hello goroutine"
}
}
向通道放入數(shù)據(jù)時確保有g(shù)oroutine正在等待著這個通道的數(shù)據(jù)敬特,若這個通道沒有g(shù)oroutine等待數(shù)據(jù)則會報錯柔吼。
fatal error: all goroutines are asleep - deadlock!
-
多個goroutine循環(huán)接收數(shù)據(jù)
例如這個代碼例子毒费,每點一次回車向一個通道發(fā)送一次數(shù)據(jù),但是一次只能有一個goroutine收到數(shù)據(jù)愈魏。如果接收完數(shù)據(jù)之后想要再次從這個通道接收數(shù)據(jù)則需要到隊伍的最后重新排隊等待觅玻。
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
i, ch, scan := 0, make(chan string), bufio.NewScanner(os.Stdin)
// goroutine1
go func() {
for {
fmt.Print(<-ch)
fmt.Println("goroutine1")
}
}()
// goroutine2
go func() {
for {
fmt.Print(<-ch)
fmt.Println("goroutine2")
}
}()
// goroutine3
go func() {
for {
fmt.Print(<-ch)
fmt.Println("goroutine3")
}
}()
for {
scan.Scan()
ch <- fmt.Sprintf("%d : Hello ", i)
i++
}
}
多個goroutine同時接收通道的一條消息
原理很簡單,舉個例子:假如柜臺前所有的人都要看一張通知單培漏,柜員A在柜臺前將通知單遞給第一個人時溪厘,安排柜員B排到隊伍的最后;隊伍中的第一個人看完通知單后將通知單遞回柜臺牌柄,然后到隊伍的最后重新排隊(此時排在柜員B的后面)畸悬,接著下一個人重復(fù)第一個人的操作,直到柜員B排到柜臺前拿走通知單珊佣,走回柜臺里(不將通知單給下一個人)蹋宦。這樣第一個看通知單的人重新回到柜臺前等待下一個數(shù)據(jù)。
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
i, ch, scan := 0, make(chan string), bufio.NewScanner(os.Stdin)
// goroutine1
go func() {
for {
/* 獲取通道里的數(shù)據(jù) */
m := <-ch
fmt.Print(m)
fmt.Println("goroutine1")
/* 處理完成之后將數(shù)據(jù)通過通道遞給下一個goroutine
ch <- m
}
}()
// goroutine2
go func() {
for {
/* 此處處理同goroutine1 */
m := <-ch
fmt.Print(m)
fmt.Println("goroutine2")
ch <- m
}
}()
// goroutine3
go func() {
for {
m := <-ch
fmt.Print(m)
fmt.Println("goroutine3")
ch <- m
}
}()
for {
scan.Scan()
/* 按下一次回車向通道發(fā)送一次數(shù)據(jù) */
ch <- fmt.Sprintf("%d : Hello ", i)
/* 向通道里傳遞數(shù)據(jù)后立即到隊伍后面重新排隊 */
<-ch
i++
}
}