ログの出力、別スレッドでやりたくなりますよね?ということでgoroutineを使って書いてみました。
package main
import (
"log"
"os"
)
func main() {
msg := make(chan string)
done := make(chan bool)
go logRoutine("log.txt", msg, done)
defer func() {
close(msg)
<-done
}()
msg <- "log1"
msg <- "log2"
}
func logRoutine(fileName string, msg chan string, done chan bool) {
fw, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
done <- true
return
}
defer fw.Close()
logger := log.New(fw, "[test]", log.LstdFlags)
for {
if message, ok := <-msg; ok {
logger.Println(message)
fw.Sync()
} else {
break
}
}
done <- true
}
使う側を見てみましょう。
msg := make(chan string)
done := make(chan bool)
go logRoutine("log.txt", msg, done)
defer func() {
close(msg)
<-done
}()
msg <- "log1"
msg <- "log2"
メッセージを書き込むchannelと、ログ出力routineの終了検知用のchannelを作ります。そしてgoで実行し、deferで後始末をして、実際に書き込んでみます。
goroutine側も見てみましょう。
// ログ用ファイルを開く
fw, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
done <- true
return
}
defer fw.Close()
logger := log.New(fw, "[test]", log.LstdFlags)
for {
if message, ok := <-msg; ok {
logger.Println(message)
fw.Sync()
} else {
// closeされていたらループを抜ける
break
}
}
// 終わったよと通知
done <- true
OpenFile()関数でファイルを開いて、log.New()関数に渡してLoggerオブジェクト生成。あとはループでchannelがcloseされるまで書き続けるという、お手本のようなgoroutineになりました。