0
点赞
收藏
分享

微信扫一扫

Go Context 简介

Context

上下文 context.Context  Go 语言中用来设置截止日期,同步信号,传递请求相关的结构体,context 与 gotoutine 有比较密切的关系,是 Go 语言中的独特设计。Go Context 简介_开发者社区

Context 作用

  • 每个 Context 都会从最顶层 Goroutine 一层一层传递到最下层,context.Context 可以在上层 Goroutine 执行出现错误,会将信号及时同步到下一次层,这样,上层因为某些原因失败时, 下层就可以停掉无用的工作,以减少资源损耗。实际应用:RPC 超时时间设置
  • context 中一般意义 context.WithValue 能从父上下文中创建一个子上下文,传值的子上下文使用 context.valueCtx 类型。WithValue 是一对 kv 类型,可用来传值,实际应用:传递全局唯一的调用链

Context 接口

Context 是 Go 语言在 1.7 版本引入的标准库接口,有以下需要实现的方法

  1. Deadlime 返回 context.Context 被取消的时间,也就是完成工作的截止时间
  2. Done 返回一个 Channel ,这个 Channel 会在当前工作完成或者被取消后关闭,多次调用 Done 方法会返回同一个Channle
  3. Err 返回 context.Context 结束的原因,只会在 Done 方法对应的 Channel 关闭时返回非空的值
  4. Value 从 context.Context 中获取对应的值,对同一个上下文来说,多次调用 Value 并传入相同的 Key 会返回相同的结果。该方法可以用来传递特定的请求。
  • 如果 context.Context 被取消,会返回 Canceled 错误;
  • 如果 context.Context 超时,会返回 DeadlineExceeded 错误;
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}

Go Context 简介_开发者社区_02在这里插入图片描述

使用 context 同步信号

创建一个过期时间为 1s 的上下文, 并向上下文传入 handle 函数,该方法会使用 500ms 的时间处理传入的请求。

package contexttest

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

func TestContext(t *testing.T) {
// 创建一个过期时间为1s的上下文
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

go handle(ctx, 500*time.Millisecond)
select {
case <-ctx.Done():
fmt.Println("main", ctx.Err())
}
}

func handle(ctx context.Context, duration time.Duration) {

select {
case <-ctx.Done():
fmt.Println("handle", ctx.Err())
case <-time.After(duration):
fmt.Println("process request with",
duration)
}
}

运行结果:

=== RUN   TestContext
process request with 500ms
main context deadline exceeded
--- PASS: TestContext (1.00s)
PASS

Context 创建

  • 根 Context: 通过 context.Backgroud() 创建
  • 子 Conetxt:context.WithCancel(parentConetxt) 创建
ctx, cancel := context.WithCancel(conetext.Background())
  • 当前 Context 被取消时,其他的子 context 都会被取消
  • 接收取消通知 <- ctx.Done()

测试代码package main

import (
"context"
"testing"
"time"
)

func isCanceled(ctx context.Context) bool {
select {
case <-ctx.Done():
return true
default:
return false
}
}

func TestCanceledByConetxt(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
for i := 0; i < 5; i++ {
go func(i int, ctx context.Context) {
for {
if isCanceled(ctx) {
break
}
}
time.Sleep(time.Second * 1)
}(i, ctx)
}
cancel()
}

欢迎关注公众号:程序员开发者社区

Go Context 简介_golang_03

关注我们,了解更多

参考资料

  • ​​https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-context/​​
  • ​​https://zhuanlan.zhihu.com/p/68792989​​
  • ​​https://github.com/golang/go/blob/41d8e61a6b9d8f9db912626eb2bbc535e929fefc/src/context/context.go#L519​​


举报

相关推荐

0 条评论