概要
- Go言語の特徴であるごるーちん(goroutine)。
-
go func_name()
と書くだけで動くと聞いて、書いてみたけどうまくいかない!とハマったのでまとめました。 -
結論:
main()
関数が終了するとごるーちんもすべて終了になるので、main()
関数内にgo func_name()
と書くだけではごるーちんが起動前にプログラム自体が死んでしまいます。解決するには、チャネルを使う方法があります。サンプルは下に。
うまくいかない例
* ↑リンク先の「Run」ボタンを押すとプログラムが実行されますgoroutine_NG.go
package main
import (
"log"
"time"
)
func sub() {
log.Println("ごるーちんが呼ばれたよ!")
time.Sleep(3 * time.Second)
log.Println("3秒経過!")
}
func main() {
log.Println("--- main start ---")
// ごるーちんの呼び出し(うまくいかない)
go sub()
log.Println("--- main finish ---")
}
実行結果
- ごるーちんが実行されない
2009/11/10 23:00:00 --- main start ---
2009/11/10 23:00:00 --- main finish ---
なんでごるーちんすぐ死んでしまうん?
- main()が終了するとすべてのプロセス(goroutineで呼び出したファンクション含む)が終了するから
- 上記だとごるーちんを呼び出した直後にmain()が終了しているためごるーちんが実行されません
- ごるーちんの終了を待ってからmain()を終了する必要があります
チャネルを使ってごるーちんの終了を待つ例
- ↑リンク先の「Run」ボタンを押すとプログラムが実行されます
goroutine_SUCCESS.go
package main
import (
"log"
"time"
)
func sub(ch chan bool) {
log.Println("ごるーちんが呼ばれたよ!")
time.Sleep(3 * time.Second)
log.Println("3秒経過!")
// 処理が終わったらチャネルに通知
ch <- true
}
func main() {
log.Println("--- main start ---")
// チャネル作成
ch1 := make(chan bool)
// ごるーちんの呼び出し
go sub(ch1)
// チャネルから通知が届くのを待つ
<-ch1
log.Println("--- main finish ---")
}
実行結果
- ごるーちんで呼び出したファンクションが無事実行されました
2009/11/10 23:00:00 --- main start ---
2009/11/10 23:00:00 ごるーちんが呼ばれたよ!
2009/11/10 23:00:03 3秒経過!
2009/11/10 23:00:03 --- main finish ---
- チャネルを知らない段階で、とりあえずごるーちん動かそうぜ!と思うとこの解決法が思い浮かばずハマりました。
- で、チャネルって何さという点についてはGo その3 1日目の記事がサンプルもあって非常に参考になります!
その他
-
The Go Playgroundの Share 機能、その場で実行できてちょっとしたサンプルを共有するのにめちゃめちゃ便利ですね!
-
The Go Playgroundの時間は、いつ実行しても同じ結果が得られるように "2009-11-10 23:00:00 UTC" に固定されているそうです
-
気になる点があれば、気軽にコメントください!