1
1

Go:分かりにくいContextを簡単なコードで解説

Posted at

Contextの基本

  • Contextの目的:context.Contextは、ゴルーチンの実行に関連する設定やシグナルを伝達するためのものです。これには、処理のキャンセル、タイムアウトの設定などが含まれます。
  • キャンセルシグナルを送る:あるゴルーチンが他のゴルーチンに「もう止めて」と伝えることができます。これは、不要な作業を止めてリソースを節約するのに役立ちます。
  • タイムアウトを設定する:特定の時間が過ぎたら、自動的にいくつかの作業を止めるように設定できます。

Contextの使い方

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {
	// Contextを作って、3秒後に自動で止めるように設定
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	// ここで5秒待ってからメッセージを出そうとする
	select {
	case <-time.After(5 * time.Second):
		fmt.Println("5秒経過: メッセージ表示")
	case <-ctx.Done(): // でも、Contextが3秒で止めるから、こっちが先に来る
		fmt.Println("キャンセルされました")
	}
}

実行結果

$ go run main.go
処理キャンセル

簡単にコードの説明

  • 最初に、context.WithTimeout(context.Background(), 3*time.Second)で「3秒後に自動で止めてね」という設定をしたContextを作ります。
  • defer cancel()は、「この関数が終わる時に、設定したContextをキャンセルしてね」という意味です。
  • selectは、「2つのことを待つけど、どっちか先に起きたらそれをやる」という意味です。
    • case <-time.After(5 * time.Second)は「5秒待つ」ということ。
    • case <-ctx.Done()は「Contextがキャンセルされた(3秒経った)らこっち」ということ。
  • この例では、5秒待つ前に3秒でContextがキャンセルされるので、「キャンセルされました」と表示されます。これは、Contextを使ってプログラムの一部を自動で止める例です。

ctx, cancel := context.WithTimeout(~~)について

  • ctx, cancel := context.WithTimeout(~~)のこの行は、タイムアウト付きのContextを作成し、それを制御するためのキャンセル関数を返します。
  • ctx(Context):ctxは、作成されたContextのインスタンスです。このContextは、設定されたタイムアウト(この例では3秒)が経過すると自動的にキャンセルされるように設定されています。タイムアウトが経過すると、ctx.Done()チャネルにシグナルが送られます。
  • cancelキャンセル関数):cancelは、Contextを手動でキャンセルするための関数です。defer cancel()とすることで、main関数が終了する際に自動的にこのキャンセル関数が呼ばれるように設定されています。

defer cancel()について

  • deferキーワード:deferキーワードは、関数が終了する際に特定の関数を実行するために使われます。つまり、現在の関数の残りの部分がすべて実行された後で、deferで指定された関数が実行されます。
  • cancel()関数:context.WithTimeout関数は、Contextをキャンセルするためのcancel関数も返します。このcancel関数を呼び出すと、Contextがキャンセルされ、関連するゴルーチンなどの処理が中断されることを意味します。
  • 使い方と意味:defer cancel()は、現在の関数(この場合はmain関数)が終了するときにcancel関数を自動的に呼び出します。これにより、Contextが確実にキャンセルされ、プログラムがきれいに終了します。

case <-について

  • selectステートメント:selectステートメントは、複数のチャネル操作を待ち受けて、準備ができた操作から順に実行するために使われます。
  • case <-:この構文は、チャネルからのデータの受信を待ち受けるために使われます。case <-ctx.Done():は、「ctx.Done()チャネルからデータ(シグナル)を受信したら、このケースのコードを実行する」という意味です。

time.Secondについて

  • 時間の単位:time.Secondは、時間の単位を表します。具体的には、1秒を意味します。
  • 使い方:time.Secondは、時間を指定する際の単位として使われます。例えば、3*time.Secondは3秒を意味します。

まとめ

プログラムの一部が長く時間がかかる場合や、特定の時間が過ぎたらやめたい場合に、contextを使うと便利です。
これにより、無駄な処理を省いたり、プログラムが固まるのを防いだりすることができます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1