随時更新
Goroutine & Channel
goroutineの終了を待つ
(http://jxck.hatenablog.com/entry/20130414/1365960707 が良記事です)
1つのgoroutineを待つだけならchannelを使えばok:
package main
import "log"
func main() {
ch := make(chan int)
go func(ch chan int) {
// do something
log.Printf("end of goroutine")
ch <- 1
}(ch)
log.Printf("waiting for goroutine")
<- ch
log.Printf("end of main")
}
複数のgoroutineを待つ場合はsync.WaitGroupを使うらしいです:
package main
import (
"log"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1) // goroutineの数だけAdd()
go func(i int) {
defer wg.Done() // goroutineを抜けたらDone()
log.Printf("goroutine: %d", i)
}(i)
}
log.Printf("waiting for goroutines")
wg.Wait() // ここでblockして待つ
log.Printf("end of main")
}
ちなみに細かいことですが、Done()が呼ばれたそばから終了するので、複数のdeferを呼ぶ場合は、Done()を"最初に"書いておかないと他のdeferが呼ばれる前にプロセスが終了してしまう可能性があります (deferはLIFOで実行されます: http://blog.golang.org/defer-panic-and-recover)
Build
debug / release buildを分ける
build tagを使います。(例えば)env packageにenv_debug.goとenv_release.goをつくって、それぞれにbuild条件を書くと、build tagにmatchするファイルだけがbuildされます。
// +build !release
package env
const DEBUG = true
// +build release
package env
const DEBUG = false
このとき、"// +build ..."は1行目に書く必要があって、且つ、1行空行が必要です。で、このpackageをimportして振る舞いを分けます。
package main
import (
"github.com/user/app/env"
)
func main() {
if env.DEBUG {
// ...
}
}
debug buildは
$ go build github.com/user/app
で、release buildは
$ go build -a -tags=release github.com/user/app
になります (build tagを変えただけの場合は、正しく全てのライブラリがbuildし直されない可能性があるので、-aが無難です)。
その他
呼び出し元のfuncを取得する
pc, _, _, _ := runtime.Caller(1)
caller_name := runtime.FuncForPC(pc).Name();
で出来ます。DEBUGフラグとかがあれば:
import (
"log"
"runtime"
"github.com/user/app/env"
)
func Debug(format string, args ...interface{}) {
if env.DEBUG {
pc, _, _, _ := runtime.Caller(1)
caller_name := runtime.FuncForPC(pc).Name();
log.Printf(caller_name + ": " + format, args...)
}
}
で、デバッグログが出力しやすくなる気がします。
packageのprefixを省略する
package main
import (
"log"
)
func main() {
log.Printf("hello")
}
とかの"log."を省略するには
import (
. "log"
)
とすると
Printf("hello")
と書けます、まめ知識です。同様に、
import (
foo "log"
)
とすれば
foo.Printf("hello")
でアクセスできます。