BackEnd

goのcontextについて

投稿日:

はじめに

これまでは何気なくcontextを扱っていたので、この機会にcontextとは何で、何ができるのかについて調べてみました。

contextとは

contextパッケージのコメントには以下のように記載されています。

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

https://pkg.go.dev/context

これによると、contextの役割は、異なるプロセル間でデッドライン、キャンセルシグナル、その他のリクエストスコープを伝達することです。

これらは特に複数のゴルーチンをまたいだ処理を行う際に力を発揮します。

また、contextを利用する最も一般的なケースとしては、HTTPサーバが挙げられます。

contextの定義

context.Contextはインタフェースとして定義されています。

contextでキャンセルシグナルを伝達する

contextを使ってキャンセルシグナルを伝達する方法を見ていきます。

cancel関数でキャンセルシグナルを伝達する

context.WithCancel 関数を使うと、親のcontextを引き継いだ子のcontextとcancel関数が返ってきます。このcancel関数を実行することで、子のcontextを渡したゴルーチンに対してキャンセルシグナルを伝達することができます。cancelシグナルを受け取ったゴルーチンは自身を終了させます。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

もちろん、複数のゴルーチンに対してもキャンセルシグナルを伝達することができます。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

このように、複数のゴルーチンに対してもキャンセルシグナルを送ることができます。

キャンセルシグナルの伝達範囲

cancel関数は、そのcontextおよび、そのcontextを親とする子のcontextに対してキャンセルシグナルを伝達します。

これはつまり、子のcontextのcancel関数から親のcontextに対してはキャンセルシグナルが伝達されないことを意味します。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

このように、1つ目のゴルーチンにはキャンセルシグナルが伝達されていない事がわかります。

子のcontextにキャンセルシグナルを伝達させない

context.WithoutCancel 関数を使うと、親のcontextのキャンセルシグナルを伝達させない子のcontextを作ることができます。

先程のコードのctx3を以下のように生成することで、ctx2のキャンセルシグナルを伝達させないようにすることができます。

実行ログは以下のとおりです。

このように、ctx3に対してctx2のキャンセルシグナルが伝達されていないことがわかります。

contextでデッドラインを伝達する

contextを使ってデッドラインを伝達する方法を見ていきます。

cancel関数でデッドラインを伝達する

context.WithDeadline 関数および、 context.WithTimeout 関数を使うことで、デッドラインを伝達することができます。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

context.WithDeadline 関数では、contextに加えてcancel関数も返却されるので、能動的にキャンセルシグナルを送ることもできます。

ちなみに、 context.WithTimeout 関数は、内部で context.WithDeadline 関数を呼び出しているだけなので、紹介は割愛します。

contextからデッドラインを確認する

contextにデッドラインが設定されているかどうかは、contextの Deadline メソッドで確認することができます。

デッドラインとキャンセルの補足

contextが返すエラー

contextには Err メソッドが定義されており、デッドラインかキャンセルシグナルが伝達された場合に取得できるようになっています。

なお、どちらも伝達されていない場合は、nilが返されます。

contextに定義されたerror型

contextパッケージには2種類のエラーが定義されており、キャンセルシグナルが伝達された場合は context.Canceled が返され、デッドラインの場合は context.DeadlineExceeded が返されます。

任意のerrorを返す

WithCancelCause 関数や WithDeadlineCause 関数を使って、任意のエラーを返すことができます。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

このように、 context.Cause 関数を使うことで、渡されたエラーを取得することができます。

キャンセル後に任意の処理を実行する

context.AfterFunc 関数を使うことで、デッドラインまたは、キャンセルシグナルが伝達された後に任意の処理を実行させることができます。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

なお、 cancel 関数を呼ぶ前に stop 関数を呼べば、 AfterFunc が呼ばれなくなります。

contextに値を持たせる

contextを使ってリクエストスコープを伝達する方法を見ていきます。

contextにValueを持たせる

context.WithValue 関数を使うことで、contextにValueをもたせることができます。持たせたValueはcontextの Value メソッドで取得することができます。

サンプルコードは以下のとおりです。

実行ログは以下のとおりです。

注意点として、同じキーに値をセットすると上書きされてしまうので、文字列などのかぶる可能性が高いものは避けるのが無難です。サンプルコードのようにキーに指定する型を定義するのが一般的です。

さいごに

普段何気なく使っているcontextの役割や使い方などへの理解が深まりました。

goのバージョンが進むにつれてcontextにも新しい機能が追加されていっているので、今後リリースノートを確認する際には注目したいと思います。

おすすめ書籍

初めてのGo言語 ―他言語プログラマーのためのイディオマティックGo実践ガイド Go言語によるWebアプリケーション開発 Go言語による並行処理

blog-page_footer_336




blog-page_footer_336




-BackEnd
-

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

【Ruby Advent Calender 2017】Rubyでスクレイピングをしてみる【11日目】

1 はじめに1.1 概要2 仕様3 ソースコード4 使用したモジュール、Gem5 対象ページを取得6 XPATHから目的のものを抜き出す7 次のページのリンクを取得する8 他のサイトの記事でも試してみ ...

rails

deviseを使ってユーザ登録フォームを作る

1 はじめに1.1 前提条件2 deviseについて2.1 deviseとは2.2 deviseでできること3 登録処理の実装3.1 Gemのインストール3.2 deviseのインストール3.3 デフ ...

laravel logo

Laravelでの署名付きURL生成

1 はじめに2 今回のサンプル3 ビュー4 ルーティング5 コントローラー5.1 署名付きURLの生成5.2 期限ありの署名付きURLの生成5.3 署名のチェック6 おまけ6.1 署名の仕組7 さいご ...

rails

configに追記したのに、rails runnerが起動しない?

1 はじめに1.1 環境2 rails runnerを使用してみる2.1 バッチファイルの作成2.2 configにパスを追記2.3 実行3 ところが…3.1 解決方法4 おまけ(runnerコマンド ...

Vue.js+TypeScriptな環境整備

1 はじめに2 vue-cliのインストール3 プロジェクトの作成3.1 機能の選択3.2 シンタックスの選択3.3 CSSプリプロセッサの設定3.4 Unit test3.5 E2E test3.6 ...

フォロー

blog-page_side_responsive

2024年12月
1234567
891011121314
15161718192021
22232425262728
293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。