ログ出力をgoroutineで行う

ツイート このエントリーをはてなブックマークに追加
1つ上へ / ブログトップへ

ログの出力、別スレッドでやりたくなりますよね?ということで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になりました。

1つ上へ / ブログトップへ