いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-482 (slogメモ-05)(テキスト形式のログ)

関連記事

Goメモ-477 (slogメモ-01)(基本的な使い方) - いろいろ備忘録日記

Goメモ-478 (slogメモ-02)(構造化ログの出力) - いろいろ備忘録日記

Goメモ-479 (slogメモ-03)(デフォルトロガー) - いろいろ備忘録日記

Goメモ-480 (slogメモ-04)(従来のlogパッケージとの連携) - いろいろ備忘録日記

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

今更ながら、Go 1.21で導入された log/slog を使ってみたりしています。

少しづつメモしていきます。今回はテキスト形式のログ(TextHandler) について。

サンプル

main.go

package main

import (
    "context"
    "log/slog"
    "os"
    "time"
)

func main() {
    var (
        rootCtx  = context.Background()
        ctx, cxl = context.WithCancel(rootCtx)
    )
    defer cxl()

    if err := run(ctx); err != nil {
        slog.Error("A fatal error occurred", "error", err)
        os.Exit(1)
    }
}

func run(_ context.Context) error {
    //
    // slogパッケージは、テキスト形式でのログ出力を簡単に実現できる。
    // ハンドラに slog.TextHandler を指定すれば良い。
    //
    // 注意点として、TextHandlerとJSONHandlerでは timeキー の出力値が少し異なる。
    //
    // - TextHandler: ベースは time.RFC3339Nano だが、ミリ秒までの精度で出力される
    // - JSONHandler: time.RFC3339Nano
    //
    // Goのソースコード go/src/log/slog/handler.go の appendRFC3339Millis() に
    // 説明が以下のように記載されている。以下、 go1.23.1 時点でのコメント。
    //
    // Format according to time.RFC3339Nano since it is highly optimized,
    // but truncate it to use millisecond resolution.
    // Unfortunately, that format trims trailing 0s, so add 1/10 millisecond
    // to guarantee that there are exactly 4 digits after the period.
    // (time.RFC3339Nanoは高度に最適化されているので、それにしたがってフォーマットするが、
    // ミリ秒の分解能を使うために切り捨てる。残念なことに、このフォーマットでは末尾の0が切り捨てられるので、
    // ピリオドの後に正確に4桁の数字があることを保証するために1/10ミリ秒を追加する。)
    //

    var (
        opt = &slog.HandlerOptions{
            Level: slog.LevelDebug,
        }
        handler = slog.NewTextHandler(os.Stdout, opt)
        logger  = slog.New(handler)
        ch      = make(chan int)
    )

    go func() {
        defer close(ch)
        for i := range 3 {
            ch <- i
            <-time.After(10 * time.Millisecond)
        }
    }()

    for i := range ch {
        logger.Debug("LOOP", "i", i)
    }

    return nil
}

実行すると以下のように出力されます。

Taskfile.yml

# https://taskfile.dev

version: '3'

tasks:
  default:
    cmds:
      - go run .

shell

$ task
task: [default] go run .
time=2024-09-30T04:57:40.005Z level=DEBUG msg=LOOP i=0
time=2024-09-30T04:57:40.015Z level=DEBUG msg=LOOP i=1
time=2024-09-30T04:57:40.025Z level=DEBUG msg=LOOP i=2

try-golang/examples/slog at main · devlights/try-golang · GitHub

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。