親Contextの都合でcancelしてほしくないが、loggerの引き回しはContextでやりたい、みたいなときにDeadline()/Done()/Err()を無視すればいいのかなぁ…と思って実装してみた。
cancelされたくないというのは、SIGINTですべてのgoroutineを停止したいんだけど、goroutineのトランザクションは完了しててほしい、みたいな。
package ctxutil import ( "context" "time" ) type withoutCancelCtx struct { parent context.Context } func (*withoutCancelCtx) Deadline() (deadline time.Time, ok bool) { return } func (*withoutCancelCtx) Done() <-chan struct{} { return nil } func (*withoutCancelCtx) Err() error { return nil } func (ctx *withoutCancelCtx) Value(key any) any { return ctx.parent.Value(key) } func WithoutCancel(parent context.Context) context.Context { return &withoutCancelCtx{parent} }
ctx = ctxutil.WithoutCancel(ctx)
ctxutil.WithoutCancel()
を読んでいる関数の上位の関数では、親ContextのDone()をチェックして、子が終わったら終了する想定。
キャンセルされたくないトランザクションはいろいろあるきがしているけど、その対応の実装例をあまり見ないような気がしている。他の人、どうしているんだろう?