关于go:Go十大常见错误第8篇并发编程中Context使用常见错误

38次阅读

共计 3401 个字符,预计需要花费 9 分钟才能阅读完成。

前言

这是 Go 十大常见谬误系列的第 8 篇:并发编程中 Context 应用常见谬误。素材来源于 Go 布道者,现 Docker 公司资深工程师 Teiva Harsanyi。

本文波及的源代码全副开源在:Go 十大常见谬误源代码,欢送大家关注公众号,及时获取本系列最新更新。

Context 是什么

Go 语言规范库里有一个 package 叫context,该 package 里定义了 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.

光看这段形容,还是很容易让人迷糊的,咱们接下来具体看看 Context 到底是什么以及能够帮忙咱们做什么事件。

Context 顾名思义,示意的是 goroutine 的上下文,Context 定义如下所示:

// A Context carries a deadline, cancellation signal, and request-scoped values
// across API boundaries. Its methods are safe for simultaneous use by multiple
// goroutines.
type Context interface {
    // Done returns a channel that is closed when this Context is canceled
    // or times out.
    Done() <-chan struct{}

    // Err indicates why this context was canceled, after the Done channel
    // is closed.
    Err() error

    // Deadline returns the time when this Context will be canceled, if any.
    Deadline() (deadline time.Time, ok bool)

    // Value returns the value associated with key or nil if none.
    Value(key interface{}) interface{}}

Context 能够通过超时设置、携带勾销信号、附加参数信息来不便 goroutine 里做相应的逻辑管制。

  • 超时管制。通过 context.WithTimeout 函数和 context.WithDeadline 函数能够创立一个有超时工夫的 Context。通过 Context 的 Done 函数能够判断是否超时了。

    func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
    func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
  • 勾销信号。通过 context.WithCancel 函数能够创立一个接管 cancel 信号的 Context。通过 Context 的 Done 函数能够判断是否收回了 cancel 信号。父 Context 收回的 cancel 信号,子 Context 也能够接管到。

    func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
  • 附加参数信息。通过 context.WithValue 函数能够给 Context 增加参数。其中 key 和 value 都是空接口类型 (interface{})。通过 Context 的Value 函数能够获取附加参数信息。

    func WithValue(parent Context, key, val any) Context

在理论开发过程中,Context 的应用流程个别是:

  • Step 1: 创立 Context,给 Context 指定超时工夫,设置勾销信号,或者附加参数(链路跟踪里常常应用 Context 里的附加参数,传递 IP 等链路跟踪信息)。
  • Step 2: goroutine 应用 Step 1 里的 Context 作为第一个参数,在该 goroutine 里就能够做如下事件:

    • 应用 Context 里的 Done 函数判断是否达到了 Context 设置的超时工夫或者 Context 是否被被动勾销了。
    • 应用 Context 里的 Value 函数获取该 Context 里的附加参数信息。
    • 应用 Context 里的 Err 函数获取谬误起因,目前起因就 2 个,要么是超时,要么是被动勾销。

有 2 点要补充:

  • 第一,Context 是能够组合的。比方,咱们能够通过 context.WithTimeout 创立一个有超时工夫的 Context,再调用 context.WithValue 增加一些附加参数信息。
  • 第二,多个 goroutine 能够共享同一个 Context,能够通过该 Context 的超时设置、携带勾销信号以及附加参数来管制多个 goroutine 的行为。

常见谬误

在 Context 应用过程中有以下几个常见谬误:

  • 第一,不执行 cancel 函数去开释 Context 资源。

    • 对于 context.WithTimeoutcontext.WithDeadlinecontext.WithCancel 函数返回的 cancel 函数,须要做执行。官网阐明如下:

      Canceling this context releases resources associated with it, so code should call cancel as soon as the operations running in this Context complete:

      参考代码示例:

      func slowOperationWithTimeout(ctx context.Context) (Result, error) {ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
          defer cancel()  // releases resources if slowOperation completes before timeout elapses
          return slowOperation(ctx)
      }
  • 第二,不加超时管制,如果执行了十分耗时的 rpc 操作或者数据库操作,就会阻塞程序。如果 rpc 调用接口或者数据库操作接口反对传递 Context 参数,倡议加上超时设置。代码示例参考如下:

    ctx, cancel := context.WithTimeout(parent, 100 * time.Millisecond)
    response, err := grpcClient.Send(ctx, request)

举荐浏览

  • Go 十大常见谬误第 1 篇:未知枚举值
  • Go 十大常见谬误第 2 篇:benchmark 性能测试的坑
  • Go 十大常见谬误第 3 篇:go 指针的性能问题和内存逃逸
  • Go 十大常见谬误第 4 篇:break 操作的注意事项
  • Go 十大常见谬误第 5 篇:Go 语言 Error 治理
  • Go 十大常见谬误第 6 篇:slice 初始化常犯的谬误
  • Go 十大常见谬误第 7 篇:不应用 -race 选项做并发竞争检测
  • Go 面试题系列,看看你会几题?

开源地址

文章和示例代码开源在 GitHub: Go 语言高级、中级和高级教程。

公众号:coding 进阶。关注公众号能够获取最新 Go 面试题和技术栈。

集体网站:Jincheng’s Blog。

知乎:无忌。

福利

我为大家整顿了一份后端开发学习材料礼包,蕴含编程语言入门到进阶常识(Go、C++、Python)、后端开发技术栈、面试题等。

关注公众号「coding 进阶」,发送音讯 backend 支付材料礼包,这份材料会不定期更新,退出我感觉有价值的材料。还能够发送音讯「进群」,和同行一起交流学习,答疑解惑。

References

  • 参考文章:https://itnext.io/the-top-10-…
  • 官网文档:https://pkg.go.dev/context
  • 官网 Context 入门介绍:https://go.dev/blog/context
  • Context 应用介绍:https://mp.weixin.qq.com/s/Po…
  • https://www.digitalocean.com/…

正文完
 0