いろいろ備忘録日記

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

Goメモ-404 (キャンセル可能なスリープ処理)(time.Sleep, time.Ticker)

関連記事

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

概要

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

周りから「time.Sleep()だとブロックしてしまうが、キャンセル出来るようにしたい」という話をちょこちょこ聞きます。

time.Sleep() は、他の言語にもあるSleep関数と同様に現在のスレッド(ゴルーチン)を指定時間分ブロックしてしまいます。

キャンセル可能なスリープ処理を行いたい場合は、コンテキストとtime.Tickerを利用するのが楽です。

サンプル

package times

import (
    "context"
    "time"

    "github.com/devlights/gomy/output"
)

// CancellableSleep は、キャンセル可能なスリープ処理のサンプルです。
//
// time.Sleep() は、ブロックしてしまうためキャンセル可能な状態で
// スリープ処理を行いたい場合は、time.Tickerを利用して処理する。
//
// # REFERENCES
//   - https://pkg.go.dev/time@go1.22.2#NewTicker
func CancellableSleep() error {
    const (
        timeFormat = time.TimeOnly + ".000"
    )

    var (
        ctx, cxl = context.WithTimeout(context.Background(), 3500*time.Millisecond)
        ticker   = time.NewTimer(5 * time.Second)
    )
    defer cxl()
    defer ticker.Stop()

    output.Stdoutl("[begin]", time.Now().Format(timeFormat))
    defer func() { output.Stdoutl("[end  ]", time.Now().Format(timeFormat)) }()

    //
    // 以下は5秒間スリープする処理があるとして、3.5秒でキャンセルします。
    // time.Sleep(5 * time.Second) とすると 5秒間 ブロックされますが
    // context.Context と *time.Ticker.C を利用してselectで待機するようにしているため
    // 先に完了した方で抜けていきます。
    //
    select {
    case <-ctx.Done():
        output.Stdoutl("[cancel]", ctx.Err())
    case <-ticker.C:
        output.Stdoutl("[sleep]", "done")
    }

    return nil
}

try-golang/examples/basic/times/time_cancallable_sleep.go at main · devlights/try-golang · GitHub

実行すると以下のようになります。

      $ task
       task: [build] go build .
       task: [run] ./try-golang -onetime

       ENTER EXAMPLE NAME: time_cancellable_sleep

       [Name] "time_cancellable_sleep"
       [begin]              07:33:29.449
       [cancel]             context deadline exceeded
       [end  ]              07:33:32.951


       [Elapsed] 3.502395005s

参考情報

https://pkg.go.dev/time@go1.22.1#Time.Format

https://x.com/func25/status/1776936187137229071

Goのおすすめ書籍


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

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