channel(一) channel用於goroutines之間的通信,讓它們之間可以進行數據交換。像管道一樣,一個goroutine_A向channel_A中放數據,另一個goroutine_B從channel_A取數據 channel 基本語法 // 因為channel是指針類型的數據類型, ...
channel(一)
channel用於goroutines之間的通信,讓它們之間可以進行數據交換。像管道一樣,一個goroutine_A向channel_A中放數據,另一個goroutine_B從channel_A取數據
channel 基本語法
// 因為channel是指針類型的數據類型,所以通過make來分配記憶體
// 使用make聲明一個channel,裡面可以存放string類型的數據
channel := make(chan string)
// 將tmp送到channel中
channel <- tmp
// 從channel中接受數據給tmp
tmp := <- channel
// 從channel中接受數據給tmp,如果沒有接受到則ok值為false
tmp,ok := <- channel
// 關閉通道channel
close(channel)
無緩衝的通道
沒有緩衝的通道,如果routine A向通道中發送了一個數據,那麼必須等到這個數據被其他routine 取出之後,才能繼續往通道里發送,嚴格遵循”一進一齣“原則,這也就要求兩個routine 在同時對同一個通道進行寫操作和取操作
- sender端向channel中send一個數據,然後阻塞,直到receiver端將此數據receive
- receiver端一直阻塞,直到sender端向channel發送了一個數據
// 兩個routine分別對一個通道進行取放操作,並且對裡面的數據+1,到2000截至
// 嚴格遵循“一進一齣”
func Routine01(wg *sync.WaitGroup, count chan int) {
defer wg.Done()
for {
// 從通道中拿取數據
res, ok := <-count
if !ok {
// 說明通道中已經沒有數據,或者已被關閉
fmt.Println("finish!")
break
}
fmt.Println(res)
if res == 2000 {
close(count)
break
}
count <- res + 1
}
}
func main() {
var wg sync.WaitGroup
// 新建一個無緩衝的通道count
count := make(chan int)
wg.Add(2)
// 創建兩個協程
for i := 0; i < 2; i++ {
go Routine01(&wg, count)
}
// 給管道里送一個數據,來開始操作
count <- 1
wg.Wait()
}
有緩衝的通道
有緩衝的通道,可以控制裡面的緩衝區大小,可以藉助通道實現非同步的取放操作
- 容量:表示buffered channel最多可以緩衝多少個數據
- 長度:表示buffered channel當前已緩衝多少個數據
- 創建buffered channel的方式為
make(chan TYPE,CAP)
// 新建Routine來模擬機器人工作
func Routine02(wg *sync.WaitGroup, count chan string) {
defer wg.Done()
for {
// 從通道中分配工作
tmp, ok := <-count
if !ok {
// 代表通道已經空了,或者已被關閉
fmt.Println("No task else!")
break
}
fmt.Println(tmp + " start!")
time.Sleep(200 * time.Millisecond)
fmt.Println(tmp + " done!")
}
}
func main() {
var wg sync.WaitGroup
// 新建一個緩衝區大小為5的通道,來管理工作
count := make(chan string, 5)
wg.Add(2)
fmt.Println("Work start!")
// 往緩衝區中放一系列待完成的工作
for i := 0; i < 5; i++ {
tmp := fmt.Sprintf("Task %d", i)
count <- tmp
fmt.Println(tmp + " in!")
}
for i := 0; i < 2; i++ {
go functions.Routine(&wg, count)
}
// 關閉通道
close(count)
wg.Wait()
}