A Tour of Go vol.8 (Goroutines)
Goroutines
・軽量なスレッド
・goキーワードに続く関数を新しいスレッド(=goroutine)で実行する
・goroutineが実行されていてもmain()が終了するとプロセスが終了する点は注意
・Message-passing communication(各プロセスはメッセージを送り合い、内容は書き変わらない)
Channels
・goroutine 間でのメッセージパッシングをするためのもの
・メッセージの型を指定できる
・bufferで1度に扱えるメッセージの量を指定できる
・送信用チャネルはクローズする必要がある
・後述のselectで複数のチャネルから同時にメッセージを受信できる
// チャネルの生成 make(chan 要素数,キャパシティ) make(chan 要素型) // チャネルへの値の送受信 チャネル <- 送信する値 <- チャネル // バッファの指定 ch := make(chan int, 100)
// 第二引数で送信先であるチャネル(変数:c)を受け取る func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } // send sum to c c <- sum } func main() { s := []int{7, 2, 8, -9, 4, 0} // int型のチャネルを生成 c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) // receive from c x, y := <-c, <-c fmt.Println(x, y, x+y) }
Select
・複数ある case のいずれかが準備できるようになるまでブロックし、準備ができた case を実行
・複数の case の準備ができている場合、 case はランダムに選択される
func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { // 変数xの値をチャネルcを通して送信 case c <- x: x, y = y, x+y // チャネルquitが準備できたら"quit"を出力 case <-quit: fmt.Println("quit") return } } } func main() { // 1:チャネル作成 c := make(chan int) quit := make(chan int) go func() { // 2:0~9まで10回反復処理 for i := 0; i < 10; i++ { // 受信したメッセージを表示 fmt.Println(<-c) } // 送信用チャネルquitにメッセージ0を送信 quit <- 0 }() // フィボナッチ関数にチャネルを引数として渡して実行 fibonacci(c, quit) }