Edited at
GoDay 9

初心者がごるーちんでハマるところ

More than 3 years have passed since last update.


概要


  • 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日目の記事がサンプルもあって非常に参考になります!


その他