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


関連記事

Go言語

goroutineとchannelとContext

1 はじめに2 並行処理と並列処理3 goroutine4 channel4.1 channelからデータ受信4.2 for-range でのデータ受信4.3 複数のchannelを受信4.4 buf ...

Go言語

mutexを使ってGoで排他処理をする

1 はじめに1.1 mutexとは2 mutexを使った排他制御2.1 失敗するケース2.2 mutexを使って排他制御した場合2.3 構造体へmutexを埋め込む3 RWMutexを使う4 さいごに ...

Laravelのchunkメソッドとcursorメソッドのメモリ使用量

1 はじめに2 テスト用のデータ準備3 get()4 chunk()5 chunkById()6 cursor()7 さいごに8 おすすめ書籍 はじめに テーブルの全レコードに一括で処理を行うバッチを ...

PHPerだけどKotlinを勉強したって良いよね その2〜コンストラクタ編〜

1 はじめに2 コンストラクタ2.1 プライマリコンストラクタ2.2 セカンダリコンストラクタ2.3 ニックネームのみを入力した人2.4 ニックネームと email を入力した人2.5 Faceboo ...

rails

Shrineをモデルに関連付けないで使用してハマったこと

1 はじめに2 アップロード時にリサイズする3 アップロード時のバリデーション4 アップロード時に古いファイルを削除する5 さいごに はじめに ShrineはRailsでのアップロードを簡単に行えるよ ...

フォロー

blog-page_side_responsive

2024年12月
1234567
891011121314
15161718192021
22232425262728
293031  

アプリ情報

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