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


関連記事

rails

関連するモデルのレコードを一緒に作成する方法

1 はじめに1.1 前提条件2 実装2.1 モデルの作成2.2 コントローラの作成2.3 Viewの作成3 さいごに はじめに フォームからレコードを作成する際に、関連するモデルのレコードを一緒に作成 ...

GraphQL

いまさら学ぶGraphQL〜概要編〜

1 はじめに2 GraphQLとは?2.1 なぜGraphQLは誕生した?2.1.1 過剰な取得2.1.2 過少な取得2.1.3 エンドポイントの管理3 GraphQLのメリットとデメリット3.1 G ...

php logo

PHPでGmail APIを利用してメールデータを取得してみる その2

1 はじめに2 メールの内容取得3 MessagePartオブジェクト3.1 件名3.2 本文4 multipartの場合4.1 本文の取得5 全文6 さいごに7 おすすめ書籍 はじめに 前回は、Gm ...

js

Moment Timezoneを使ってJavaScriptで日付を変換する

1 はじめに2 Moment Timezone2.1 セットアップ2.2 使用例3 Moment Timezoneの機能3.1 タイムゾーンの一覧を表示する3.2 現在のタイムゾーンを表示する3.3 ...

Rust入門してみた (構造体 / トレイト)

1 はじめに2 構造体2.1 メソッド2.1.1 関連メソッド2.2 トレイト2.2.1 構造体のフィールドの1つとして、トレイトのインスタンスを持つ場合2.3 derive属性3 おすすめ書籍 はじ ...

フォロー

blog-page_side_responsive

2024年12月
1234567
891011121314
15161718192021
22232425262728
293031  

アプリ情報

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