了解Golang上下文超时

时间:2018-12-07 21:23:09

标签: mongodb go

我无法理解如何检查上下文是否超出了超时设置的期限,或者我是否应该进行检查?

这是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")
  }

我应该明确检查吗?如果没有,我什么时候应该使用显式检查?谢谢您的时间和帮助!

2 个答案:

答案 0 :(得分:2)

问题第二部分中的select代码是Connect方法中的代码。那里正在检查ctx.Done()是否已准备好发送。如果是,则由于发生超时或调用了cancel()而取消了上下文。

错误是价值。这样对待他们。如果了解错误原因(网络中断,意外数据或超时?)很重要,则应进行检查并采取相应措施。如果无论原因如何,从错误中恢复都相同,则检查错误并不重要。

答案 1 :(得分:1)

context最适合用来管理事物的生命周期。因此,如果您正在执行某些操作(例如,处理文件),则应检查上下文,以确保未处理该过程。

有两种检查context是否已取消或超时的方法:

  1. Context.Done()-返回取消关联时将关闭的通道。
  2. Context.Err()-如果取消了上下文,这将返回错误。

选择最适合您的需求。如果您正在处理通道,则在context.Done()中使用select会很好。如果您在读取for时使用io.Reader循环,那么检查context.Err()会更容易。

总而言之,如果您要开始的事情也需要上下文,那么如果希望取消该新的“事物”,则应该始终使用已有的上下文。