Goroutines
Goroutinesは軽量なスレッド。go
と記述するだけで別スレッドで処理が実装される。
go f(x, y, z)
Channels
channelを使用してgoroutine間でデータの送受信を行える。
channelの生成
ch := make(chan int)
channelの送受信
ch <- v // v をチャネル ch へ送信する v := <-ch // ch から受信した変数を v へ割り当てる
送受信の例。x, y := <-c, <-c
でchannel cを2回受信するまで待つ。
func sum(c chan int) { c <- 10 // send sum to c } func main() { c := make(chan int) go sum(c) go sum(c) x, y := <-c, <-c // receive from c fmt.Println(x, y, x+y) // 10 10 20 }
Buffered Channels
channelはバッファのような使い方も可能。バッファが詰まった時は、チャネルへの送信をブロックする。別のgoroutineにchannelを渡す場合はバッファサイズは考慮されないみたい。
バッファファイズの指定
ch := make(chan int, 2)
バッファの送受信
func main() { ch := make(chan int, 2) ch <- 1 ch <- 2 fmt.Println(<-ch) fmt.Println(<-ch) }
Range and Close
送り手は、送信する必要がなくなったチャネルを close できる。
func name(n int, c chan int) { c <- n close(c) }
channelの状態確認
v, ok := <-ch
for i := range c
でchannelが閉じられるまで受信を待ち続ける
func main() { c := make(chan int) go name(10, c) for i := range c { fmt.Println(i) } }
Select
select は、複数あるcaseのいずれかが準備できるようになるまでブロックし、準備ができたcaseを実行する。複数のcaseの準備ができている場合、case はランダムに選択される。
func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { case c <- x: 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) } quit <- 0 }() //select で c <- x: の条件が10回満たされる fibonacci(c, quit) }
Default Selection
どの case も準備ができていないのであれば、 select の中の default が実行される。
select { case i := <-c: // use i default: // receiving from c would block }
sync.Mutex
多分でJavaでいうsynchronizedのようなことができる。はず。
sync.Mutex.Lock
〜 sync.Mutex.Unlock
までの処理はgoroutine間で直列に実行される。
リンク
リンク