Golang context (上下文)是什么

Golang context (上下文)是什么?

介绍

Context 是 golang 中十分重要的接口,用于定义 goroutine 中的上下文信息,context 常用于以下几种情况:

  • 数据传递:在多个 goroutine 中传递数据
  • 超时管理:通过配置超时时间,可以方便地配置协程的终止时间
  • 终止协程:通过使用 cancel() 方法,协程可以很方便地终止,可以批量管理多个协程的终止

Context 接口

// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {

    Done() <-chan struct{}

    Deadline() (deadline time.Time, ok bool)
    
    Err() error
    
    Value(key interface{}) interface{}
}

根节点和派生节点

我们可以为 context 创建根节点和派生节点,为树形结构,当根节点被 cancel() 或超时终止时,它的所有派生节点也会被终止,根节点的数据也会被所有派生节点共享。

 

图片

创建根节点

ctx := context.Background() // 创建空白 context

ctx2 := context.TODO() // TODO 同样是空白 context

创建派生节点

使用 context.WithXXX() 创建派生 context

package main

import (
 "context"
 "fmt"
)

func main() {
 ctx := context.WithValue(context.Background(), "base""baseVal")

 ctx1 := context.WithValue(ctx, "ctx1""ctx1Val")
 ctx2 := context.WithValue(ctx, "ctx2""ctx2Val")
 ctx3 := context.WithValue(ctx, "ctx3""ctx3Val")

 fmt.Println(ctx)
 fmt.Println(ctx1)
 fmt.Println(ctx2)
 fmt.Println(ctx3)
}

// 结果:
// context.Background.WithValue(type string, val baseVal)
// context.Background.WithValue(type string, val baseVal).WithValue(type string, val ctx1Val)
// context.Background.WithValue(type string, val baseVal).WithValue(type string, val ctx2Val)
// context.Background.WithValue(type string, val baseVal).WithValue(type string, val ctx3Val)

WithValue()

context.WithValue() 可以用于创建派生节点并添加键值数据,同时保留父级 context 所有的数据

WithDeadline() WithTimeout()

context.WithDeadline() 和 context.WithTimeout() 可以用来创建带有超时控制的 context

WithTimeout(1*time.Second) 等同于 WithDeadline(time.Now().Add(1*time.Second))

package main

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

func main() {
 ctx, _ := context.WithTimeout(context.Background(), 3*time.Second)

 go func(ctx1 context.Context) {
  for {
   select {
   case <-ctx1.Done():
    fmt.Println("time out")
    return
   default:
    fmt.Println("running...")
    time.Sleep(time.Second)
   }
  }
 }(ctx)

 time.Sleep(5 * time.Second)
}

// 结果:
// running...
// running...
// running...
// time out

WithCancel()

使用 WithCancel() 可以创建手动终止的 context 执行 cancel() 即可手动终止

package main

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

func main() {
 ctx, cancel := context.WithCancel(context.Background())

 go func(ctx1 context.Context) {
  for {
   select {
   case <-ctx1.Done():
    fmt.Println("canceled")
    return
   default:
    fmt.Println("running...")
    time.Sleep(time.Second)
   }
  }
 }(ctx)

 time.Sleep(3*time.Second)
 cancel()
 time.Sleep(5 * time.Second)
}

// 结果:
// running...
// running...
// running...
// canceled

图片

图片

面试宝典 · 目录
上一篇Golang channel (信道) 是什么?
阅读原文
阅读 284
 
作者已设置关注7天后才可留言
 
 
 
 
 
 
 
posted @   技术颜良  阅读(70)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
历史上的今天:
2023-04-07 KVM--虚拟机备份还原
2023-04-07 ansible_python_interpreter指定python版本
2023-04-07 【ansible】facts 获取硬件信息
2023-04-07 ansible-galaxy命令快速创建角色框架
2022-04-07 golang判断接口变的类型与指针切片使用法(重要)
2022-04-07 gin BindJSON
2022-04-07 json.stringify()的妙用,json.stringify()与json.parse()的区别
点击右上角即可分享
微信分享提示