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言語による並行処理

page_footer_responsive




-BackEnd
-

執筆者:

免責事項

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


comment

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

CAPTCHA


関連記事

rails

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

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

aws

ALB+EC2な環境でhttpをhttpsにリダイレクトする

1 はじめに1.1 前提条件2 ALBの設定3 Nginxの設定3.1 注意点4 さいごに はじめに httpsに対応済みのWebサイトの場合、httpでアクセスされた時にhttpsでリダイレクトする ...

laravel logo

コードでわかるLaravelのブラウザ認証

1 はじめに1.1 認証機能の概要2 Controller3 SessionGuard3.1 fireAttemptEvent3.2 retrieveByCredentials3.3 hasValid ...

Go言語

[Go初心者]テストについて学習

1 はじめに2 テスト2.1 エラーの値を比較する2.2 エラーの型を比較する3 httptest3.1 httptestの使い方4 さいごに5 おすすめ書籍 はじめに 今回はGo言語のテストについて ...

Go言語

Goのfmt.print系関数のまとめ

1 はじめに2 print関数の命名規則3 各print関数の説明3.1 Print(標準出力へ出力)系関数3.2 Sprint(文字列を出力)系関数3.3 Fprint(ファイルへ出力)系関数4 書 ...

フォロー

blog-page_side_responsive

2024年12月
1234567
891011121314
15161718192021
22232425262728
293031  

アプリ情報

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