昨天簡單介紹要如何使用 Goroutines,今天就繼續延續下去吧
今天要介紹的是了 channels (通道)
channels 具有 發送/接收 阻塞的特性,所以可以用來等待 Goroutines 完成工作
下面我們就來實際操作一下
ch := make(chan <TYPE>, <Buffered Size>)
ch <-
<-ch
ch := make(chan string) // 透過 make 建立一個字串型別的 channels (通道)
ch <- "ok" // 傳值到 channels 裡面 (發送)
<-ch // 從 channels 裡面讀值出來 (接收)
channels 又分為 (1)unbuffered (2)buffered 這兩種
預設宣告時如果沒給 buffer size 的話,就會是 unbuffered channels
有宣告的話,宣告時會長成像這樣 ch := make(chan string, 2)
既然有給了 buffer,當傳入超過 buffer size 的值時,就會發生阻塞 (Block)
當阻塞 (Block) 一直無法解決的話,就會變成死鎖 (Deadlock)
像是下面這個例子
package main
import "fmt"
func main() {
ch := make(chan string, 2)
ch <- "Hello"
ch <- "World"
ch <- "!"
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
輸出結果如下
如果覺得分辨現在是 發送/接收 太難的話,有個簡單的方法
就是看 channels 變數現在是位於 <-
(通道操作符) 的左邊還是右邊
如果 channels 變數現在是位於 <-
的左邊的話,那麼現在就是 發送 (Example:ch <- "ok"
)
如果 channels 變數現在是位於 <-
的右邊的話,那麼現在就是 接收 (Example:<-ch
)
是不是瞬間覺得變簡單了呢~
package main
import (
"fmt"
"time"
)
func say(s string, ch chan string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
ch <- "done"
}
func main() {
ch := make(chan string)
go say("world", ch)
go say("hello", ch)
v := <-ch
vv := <-ch
fmt.Println(v, vv)
}
下面就來講解用 channels 改寫後的 Code
首先是原本的 func say(s string)
,這邊我們多傳遞一個 chan string
型別的 channels 變數
改寫後就變成 func say(s string, ch chan string)
-> Line 8
接著在執行完後,向 channels 傳遞 done 字串 ch <- "done"
-> Line 13
首先,我們先宣告一個 字串型別的 channels 變數 ch
-> Line 17
接著將兩個 say()
function 前面都加上 go
修飾字,加入 Goroutines,
並將 channels 變數 ch
傳入 say()
-> Line 19~20
接著從 channels 中讀取在 Line 13 發送的 done 字串,並輸出 -> Line 22~24
從下圖可以看到,hello 跟 world 都分別輸出五次後,才輸出 done
今天簡單介紹了 Goroutines 中的 channels 用法
個人覺得用起來算是簡單,應該可以快速上手
明天要來介紹的是 Goroutines 中的 select 用法
明天見~