概要
以前チャネルで同じような動きするものを記事にしました。
context.Contextを受けるバージョンもついでに作成。中で上の記事で作った関数を呼んでいるだけですがw
サンプル
package ctxs import ( "context" "github.com/devlights/gomy/chans" ) // WhenAny は、chans.WhenAny() の context.Context 版です. // // 指定したコンテキストのどれかが完了したら完了となる context.Context を生成して返します. // // Example: // // <-ctxs.WhenAny(procCtx, ctx1, ctx2, ctx3).Done() // func WhenAny(pCtx context.Context, c ...context.Context) context.Context { ctx, cancel := context.WithCancel(pCtx) go func(dones []<-chan struct{}) { defer cancel() select { case <-ctx.Done(): case <-chans.WhenAny(dones...): } }(ToDoneCh(c...)) return ctx }
gomy/whenany.go at master · devlights/gomy · GitHub
実行イメージは以下の感じ
package ctxs_test import ( "context" "fmt" "testing" "time" "github.com/devlights/gomy/ctxs" ) func ExampleWhenAny() { var ( rootCtx = context.Background() mainCtx, mainCancel = context.WithCancel(rootCtx) procCtx, procCancel = context.WithTimeout(mainCtx, 1*time.Second) ) defer mainCancel() defer procCancel() ctx1 := ctxs.StartGoroutine(procCtx, 100*time.Millisecond) ctx2 := ctxs.StartGoroutine(procCtx, 200*time.Millisecond) ctx3 := ctxs.StartGoroutine(procCtx, 300*time.Millisecond) start := time.Now() <-ctxs.WhenAny(procCtx, ctx1, ctx2, ctx3).Done() elapsed := time.Since(start) fmt.Printf("elapsed: %vmsec\n", elapsed.Milliseconds()) // Output: // elapsed: 100msec }
gomy/whenany_test.go at master · devlights/gomy · GitHub
$ go test ./ctxs/ -v -run "^ExampleWhenAny$" === RUN ExampleWhenAny --- PASS: ExampleWhenAny (0.10s) PASS ok github.com/devlights/gomy/ctxs 0.102s
最初に完了したタスクの時間で完了していますね。
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場