web-dev-qa-db-ja.com

Golangコンテキストタイムアウトについて

コンテキストがタイムアウトによって設定された期限を超過したかどうかを確認する方法を理解できない、またはまったく確認する必要があるか?

これは、mongo-go-driverのスニペットです。

_client, err := NewClient("mongodb://foo:bar@localhost:27017")
if err != nil { return err }
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
err = client.Connect(ctx)
if err != nil { return err }
_

このコードを読んで、コンテキストが期限を超えているかどうかを知るにはどうすればよいですか?私が単純に理解している(または理解していない)ことから、err = client.Connect(ctx)行は期限を超過した場合(超過した場合)を含むエラーを表示します。したがって、明示的に確認する必要さえないと思いますか?

しかし、その後、コンテキストの仕組みをよりよく理解するためにインターネットを見回しながら、以下のようにコンテキストを明示的にチェックする選択ケースの使用に遭遇します( http://p.agnihotry.com/からのコードスニペットpost/understanding_the_context_package_in_golang / ):

_//Use a select statement to exit out if context expires
  select {
  case <-ctx.Done():
    fmt.Println("sleepRandomContext: Time to return")
  case sleeptime := <-sleeptimeChan:
    //This case is selected when processing finishes before the context is cancelled
    fmt.Println("Slept for ", sleeptime, "ms")
  }
_

明示的にチェックする必要がありますか?そうでない場合、いつ明示的チェックを使用する必要がありますか?お時間をいただきありがとうございます!

9
Leesa

質問の2番目の部分のselectコードは、Connectメソッドのコードがどのようになるかを示しています。そこで、ctx.Done()が送信準備ができているかどうかをチェックしています。そうである場合、タイムアウトが発生したか、cancel()が呼び出されたため、コンテキストはキャンセルされました。

エラーは値です。それらとして扱います。エラーの原因を理解することが重要な場合(ネットワークダウン?予期しないデータ?タイムアウト?)、チェックを実行し、それに応じて対処する必要があります。原因に関係なくエラーからの回復が同じ場合、エラーのチェックはas重要ではありません。

4
sberry

contextは、何かのライフサイクルを管理するのに最適です。したがって、何かを実行している場合(ファイルの処理など)は、コンテキストをチェックして、プロセスが処理されていないことを確認する必要があります。

contextがキャンセルされたか、タイムアウトになったかどうかを確認する方法は2つあります。

  1. Context.Done()-これは、コンテキストがキャンセルされたときに閉じられるチャネルを返します。
  2. Context.Err()-コンテキストがキャンセルされた場合、これはエラーを返します。

ニーズに最適なものを選択してください。チャンネルで物事をしている場合、selectcontext.Done()を使用するとうまくいきます。 _io.Reader_の読み取り中にforループを使用している場合、context.Err()を確認する方が簡単です。

つまり、コンテキストを取得するものを開始する場合、キャンセルした場合に新しい「もの」をキャンセルしたい場合は、常に既存のコンテキストを使用する必要があります。

2
poy