鱒身(Masu_mi)のブログ

知った事をメモする場所。

Golang: contextを使ってみる

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

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

// 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")
  }
}