Golang: contextを使ってみる

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 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