A Tour of Goでの説明
Channels
チャネル( Channel )型は、チャネルオペレータの <- を用いて値の送受信ができる通り道です。
https://go-tour-jp.appspot.com/concurrency/2
ゴルーチン間で値のやり取り
ゴルーチンは非同期だけど、チャネルを使って同期させる。
情報処理検定で出てくる、キュー(先入れ先出し、FIFO)の動作。最初にチャネルに送信したデータが最初に受信される。スタック(後入れ先出し、LIFO)ではないイメージ。
mainゴルーチンの最後にチャネル受信を用意しておくと、全終了を待たせることができる。
デットロック
チャネルへの送信操作は、そのデータが受信されるまでゴルーチンをブロックするため、同じゴルーチン内でチャネルの送受信を行うとデッドロックが発生する。→バッファ付きチャネルを使用すれば解消する。
試してみた
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(5 * time.Second) // 二秒
ch1 <- 1
}()
go func() {
time.Sleep(3 * time.Second) //一秒
ch2 <- 2
}()
for i := 0; i < 2; i++ {
select { //コードの記載順序に関係なく、先に到達した方が実行される
case x := <-ch1:
fmt.Println(x)
case y := <-ch2:
fmt.Println(y)
}
}
}
/* A Tour of Goのselect
package main
import "fmt"
func fibonacci(c, quit chan int) {
x, y := 0, 1
for { //3.無限ループ
select {
case c <- x: //4.ここで1に値が送られる、10回繰り返す
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c) //1.ここでいったん止まり、2が実行され、10回送られてきた後、forを抜ける
}
quit <- 0 //5.2の呼び出しを終了させる
}()
fibonacci(c, quit) //2.呼び出す
}
*/