Golang: contextを使ってみる

context について調べたので試しにos.Signal を受け取るとキャンセルを実行するcontext.WithCancelBySignal()を作った。

書いてから振り返るとcontext はトランザクション単位で用いるがos.Signal はプロセス全体に関わるため概念が一致しづらい。 exec.CommandContext()SIGKILL を飛ばしてしまうので子プロセスは直ちに死ぬ。そのままでは使えず相性が悪い。 ただ作ったのでとりあえず残す。

 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627
// WithCancelBySignal returns context cancelable by signal
func WithCancelBySignal(parent context.Context, sigs ...os.Signal) (ctx context.Context) {
  ctx, cancel := context.WithCancel(parent)
  go func() {
    sc := make(chan os.Signal)
    signal.Notify(sc, sigs...)
    select {
    case <-ctx.Done():
    case <-sc:
    }
    cancel()
  }()
  return ctx
}

func main() {
  ctx := WithCancelBySignal(context.Background(), syscall.SIGTERM)
  LOOP:
  for {
    select {
    case <-ctx.Done():
      break LOOP
    default:
    }
    fmt.Println("in loop")
  }
}
comments powered by Disqus