Go の context のとりあえずこれだけ

投稿日: 2025-11-25

非同期処理とか知らなくても、まず最低限知っておくべき Go の context について。

これを書いている人について

  • Go の非同期処理についてちょっと学んだことはあるけど、実際にそれを必要とするコードを書いたことがないので、ほとんど身についていない
    • ぶっちゃけ chan にあまり馴染みがない
      • 「閉じた chan に送信するのは panic になるんだっけ?」とか「同じ chan を複数回 close するのは panic にならないんだっけ?」とかを毎回調べている
  • context.Context は done チャネルとかが出てくるから、触る必要があるたびに億劫に感じる
  • goroutine をほとんど使ったことがない
    • select とか毎回調べ直す
  • とりあえず、オーソドックスな CRUD を行う Web サービスの開発が出来れば OK

こんな人が、今後少しでも気持ち良く Go のコードを読み書き出来るように、という思いで書いていきます。

とりあえず context.Context をバケツリレーすれば良い

身も蓋もない気がするが、正直、単純な Web サービスを開発する分にはこの意識「だけ」で良いと思う。

context.Context を受け取る関数やメソッドというのは、大抵は以下のように error を返すシグニチャになっている。

func doSomething(ctx context.Context) error {
    ...
}

この関数を見て、以下のような印象を持つと良い。

  • DB や network など何かしらの IO を伴うような、失敗が想定され、かつ、時間のかかる処理を行っている。
  • 渡した context.Context 経由で、関数の処理の途中でキャンセルされるかもしれない。そして、キャンセルされたときは error が返ってくる。

関数の中で何かしらのトラブルはあるかもしれないが、呼び出す側は 「返ってくるエラーをチェックする」 という一点だけ集中すれば良い。

ctx.Done() チャネルとかは気にしなくてよい

DB へのクエリや外部の Web API へリクエストするコードを書くときは頻繁にあるが、ライブラリを使う上では ctx を渡すだけで良い。 ちゃんとしたライブラリなら、内部でキャンセルを検知するために ctx.Done() の監視などを行っていると思うが、使う側は気にしなくてよい。

独自で goroutine を生成する場合などは、ctx.Done() の監視とともに goroutine の管理を行うコードを書く必要があると思う。 ただ、やはり単純な Web サービスを開発するにあたっては、そのような場面はあまりないと思う。

ctx.Err() は少しだけ気にかけておく

ctx.Err() を気にする」というよりは「このメソッドで返ってくる可能性のある、context パッケージで定義されるエラーについて知っておいた方がよい」という方が正しいかもしれない。

重い処理を行う関数がキャンセルされたときに返される error は、context パッケージで定義される専用のエラーか、またはそれをラップしたものが返されると期待される。 そのあたりの知識があれば、適切なエラーハンドリングが選べるかもしれないので、大雑把にでも概観しておくのが良いと思う。

能動的にキャンセルしたい場合は?

context.WithTimeout() でタイムアウトしてキャンセルが通知される ctx を生成する、とかが一番有り得そうかつ簡単かと思う。

ただ、これも基本的には渡された ctx をそのまま何もせずバケツリレーすれば、ほとんどのケースでは問題ない気がする。 それこそ、先日書いた「HTTP リクエストのキャンセルの記事」のように、 リクエストが保持する ctx をそのまま渡せば、自然な形でキャンセルを考慮したコードを書けたことになる。


以上です。 お粗末な内容なので公に書くのはちょっと気が引けますが、少なくとも自分は毎回困っているので、しょうがなく書き残すことにしてみました。