goroutineとはなにか?
軽量スレッドである、並行処理で複数のスレッドが立てられる
「go」というシンプルなメソッドを使ってスレッドを立てる
「channel」は複数のgoroutineにメッセージを送るもの
また「select」は複数のchannelを管理するものである
mainの関数が終了しないようにgoroutineを制御する仕組みは「channel」か「sync」を使用する
以下の例はchannelを使用して複数のリクエストを並行処理で書いてある例である。
go
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func getStatus(urls []string) <-chan string {
statusChan := make(chan string)
for _, url := range urls {
go func(url string) {
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
statusChan <- res.Status
}(url)
}
return statusChan
}
func main() {
timeout := time.After(time.Second)
urls := []string{
"http://example.com",
"http://example.net",
"http://example.org",
}
statusChan := getStatus(urls)
for {
select {
case status := <-statusChan:
fmt.Println(status)
case <-timeout:
break
}
}
}
syncを使って書くと以下のようになる
go
package main
import (
"log"
"sync"
"net/http"
)
func getStatus(urls []string) {
wait := new(sync.WaitGroup)
for _, url := range urls {
wait.Add(1)
go func(url string) {
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
log.Println(url, res.Status)
wait.Done()
}(url)
}
wait.Wait()
}
func main() {
urls := []string{
"http://example.com",
"http://example.net",
"http://example.org",
}
getStatus(urls)
}
Do not communicate by sharing memory;instead, share memory by communicating.
の原則につきgoroutineの管理はchannelを使用してメッセージを送ってやりとりするのが望ましい。
参考URL
http://gihyo.jp/dev/feature/01/go_4beginners/0005
https://github.com/astaxie/build-web-application-with-golang/blob/master/ja/02.7.md
http://jxck.hatenablog.com/entry/20130414/1365960707