GOルーチンおさらい

基本的なGOルーチン

sample.go

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println(1)
    go routine()
    fmt.Println(3)
}

func routine() {
    time.Sleep(1 * time.Second)
    fmt.Println(2)
}

実行結果

[vagrant@localhost 20160404]$ go run sample.go
1
3

main()が終了すると共に終了となる。 GOルーチンの処理を最後まで実行させる為、main側で処理が終わった事の通知を受け取るまで待機

package main

import (
    "fmt"
    "time"
    "log"
)

func main() {
    // チャンネルの作成
    ch := make(chan string)
    fmt.Println(1)
    go routine(ch)

    // チャンネルのメッセージを受信(ここで受信するまで待ちます)
    res, ok := <- ch
    log.Printf("res -> %v, ok -> %v", res, ok) //  
    fmt.Println(3)
}

func routine(ch chan string) {
    time.Sleep(2 * time.Second)
    fmt.Println(2)
    // チャンネルにメッセージ"finish"を送信
    ch <- "finish"
}

実行結果

[vagrant@localhost 20160404]$ go run sample.go 
1
2
2016/04/04 14:39:52 res -> finish, ok -> true
3

メッセージを受信するまでWaitし、順番に処理される事が確認できました。<-ch で受信結果を受け取ると、第一引数にメッセージ、第二引数に受信結果を受け取れます。

バッファリング

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

実行結果

1
2

バッファを超える数を指定するとFatal Error

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    ch <- 3
    fmt.Println(<-ch)
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /home/vagrant/work/20160404/buff.go:9 +0xc4
exit status 2

Channelクローズ

v, ok := <-ch

で第二引数でチャンネルクローズしたかどうかを受け取れる

package main

import (
    "fmt"
)

func routine(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

func main() {
    c := make(chan int, 10)
    go routine(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}

実行結果

0
1
1
2
3
5
8
13
21
34

Select

package main

import "fmt"

func routine(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
    }() 
    routine(c, quit)
}

実行結果

0
1
1
2
3
5
8
13
21
34
quit

GO TOURからの拝借コードとなりますが、自分自身の備忘という事で。今後は実用例などもアップしていこうと思います