当前位置: 首页 > news >正文

【Golang】Golang进阶系列教程--Go 语言 context 都能做什么?

文章目录

  • 前言
  • 核心是 Context 接口:
  • 包含四个方法:
  • 遵循规则
  • WithCancel
  • WithDeadline
  • WithTimeout
  • WithValue

前言

很多 Go 项目的源码,在读的过程中会发现一个很常见的参数 ctx,而且基本都是作为函数的第一个参数。

为什么要这么写呢?这个参数到底有什么用呢?带着这样的疑问,我研究了这个参数背后的故事。
开局一张图:

核心是 Context 接口:

// A Context carries a deadline, cancelation 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{}
}

包含四个方法:

  • Done():返回一个 channel,当 times out 或者调用 cancel 方法时。
  • Err():返回一个错误,表示取消 ctx 的原因。
  • Deadline():返回截止时间和一个 bool 值。
  • Value():返回 key 对应的值。

有四个结构体实现了这个接口,分别是:emptyCtx, cancelCtx, timerCtx 和 valueCtx。

其中 emptyCtx 是空类型,暴露了两个方法:

func Background() Context
func TODO() Context

一般情况下,会使用 Background() 作为根 ctx,然后在其基础上再派生出子 ctx。要是不确定使用哪个 ctx,就使用 TODO()。
另外三个也分别暴露了对应的方法:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context

遵循规则

在使用 Context 时,要遵循以下四点规则:

  • 不要将 Context 放入结构体,而是应该作为第一个参数传入,命名为 ctx。
  • 即使函数允许,也不要传入 nil 的 Context。如果不知道用哪种 Context,可以使用 context.TODO()。
  • 使用 Context 的 Value 相关方法只应该用于在程序和接口中传递和请求相关的元数据,不要用它来传递一些可选的参数。
  • 相同的 Context 可以传递给不同的 goroutine;Context 是并发安全的。

WithCancel

go复制代码func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

WithCancel 返回带有新 Done 通道的父级副本。当调用返回的 cancel 函数或关闭父上下文的 Done 通道时,返回的 ctx 的 Done 通道将关闭。

取消此上下文会释放与其关联的资源,因此在此上下文中运行的操作完成后,代码应立即调用 cancel。

举个例子:
这段代码演示了如何使用可取消上下文来防止 goroutine 泄漏。在函数结束时,由 gen 启动的 goroutine 将返回而不会泄漏。

package mainimport ("context""fmt"
)func main() {// gen generates integers in a separate goroutine and// sends them to the returned channel.// The callers of gen need to cancel the context once// they are done consuming generated integers not to leak// the internal goroutine started by gen.gen := func(ctx context.Context) <-chan int {dst := make(chan int)n := 1go func() {for {select {case <-ctx.Done():return // returning not to leak the goroutinecase dst <- n:n++}}}()return dst}ctx, cancel := context.WithCancel(context.Background())defer cancel() // cancel when we are finished consuming integersfor n := range gen(ctx) {fmt.Println(n)if n == 5 {break}}
}

输出:

2
3
4
5

WithDeadline

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)

WithDeadline 返回父上下文的副本,并将截止日期调整为不晚于 d。如果父级的截止日期已经早于 d,则 WithDeadline(parent, d) 在语义上等同于 parent。

当截止时间到期、调用返回的取消函数时或当父上下文的 Done 通道关闭时,返回的上下文的 Done 通道将关闭。

取消此上下文会释放与其关联的资源,因此在此上下文中运行的操作完成后,代码应立即调用取消。

举个例子:
这段代码传递具有截止时间的上下文,来告诉阻塞函数,它应该在到达截止时间时立刻退出。

package mainimport ("context""fmt""time"
)const shortDuration = 1 * time.Millisecondfunc main() {d := time.Now().Add(shortDuration)ctx, cancel := context.WithDeadline(context.Background(), d)// Even though ctx will be expired, it is good practice to call its// cancellation function in any case. Failure to do so may keep the// context and its parent alive longer than necessary.defer cancel()select {case <-time.After(1 * time.Second):fmt.Println("overslept")case <-ctx.Done():fmt.Println(ctx.Err())}
}

输出:

context deadline exceeded

WithTimeout

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

WithTimeout 返回 WithDeadline(parent, time.Now().Add(timeout))。
取消此上下文会释放与其关联的资源,因此在此上下文中运行的操作完成后,代码应立即调用取消。
举个例子:
这段代码传递带有超时的上下文,以告诉阻塞函数应在超时后退出。

package mainimport ("context""fmt""time"
)const shortDuration = 1 * time.Millisecondfunc main() {// Pass a context with a timeout to tell a blocking function that it// should abandon its work after the timeout elapses.ctx, cancel := context.WithTimeout(context.Background(), shortDuration)defer cancel()select {case <-time.After(1 * time.Second):fmt.Println("overslept")case <-ctx.Done():fmt.Println(ctx.Err()) // prints "context deadline exceeded"}}

输出:

context deadline exceeded

WithValue

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

WithValue 返回父级的副本,其中与 key 关联的值为 val。
其中键必须是可比较的,并且不应是字符串类型或任何其他内置类型,以避免使用上下文的包之间发生冲突。 WithValue 的用户应该定义自己的键类型。

为了避免分配给 interface{},上下文键通常具有具体的 struct{} 类型。或者,导出的上下文键变量的静态类型应该是指针或接口。

举个例子:
这段代码演示了如何将值传递到上下文以及如何检索它(如果存在)。

package mainimport ("context""fmt"
)func main() {type favContextKey stringf := func(ctx context.Context, k favContextKey) {if v := ctx.Value(k); v != nil {fmt.Println("found value:", v)return}fmt.Println("key not found:", k)}k := favContextKey("language")ctx := context.WithValue(context.Background(), k, "Go")f(ctx, k)f(ctx, favContextKey("color"))
}

输出:

ound value: Go
key not found: color

本文的大部分内容,包括代码示例都是翻译自官方文档,代码都是经过验证可以执行的。如果有不是特别清晰的地方,可以直接去读官方文档。

相关文章:

【Golang】Golang进阶系列教程--Go 语言 context 都能做什么?

文章目录 前言核心是 Context 接口&#xff1a;包含四个方法&#xff1a;遵循规则WithCancelWithDeadlineWithTimeoutWithValue 前言 很多 Go 项目的源码&#xff0c;在读的过程中会发现一个很常见的参数 ctx&#xff0c;而且基本都是作为函数的第一个参数。 为什么要这么写呢…...

画图干货!14种uml图类型及示例

1. 什么是 UML UML 是统一建模语言的缩写。UML 图是基于 UML&#xff08;统一建模语言&#xff09;的图表&#xff0c;目的是直观地表示系统及其主要参与者、角色、动作、工件或类&#xff0c;以便更好地理解、更改、维护或记录信息关于系统。简而言之&#xff0c;UML 是一种…...

计算机视觉实验:人脸识别系统设计

实验内容 设计计算机视觉目标识别系统&#xff0c;与实际应用有关&#xff08;建议&#xff1a;最终展示形式为带界面可运行的系统&#xff09;&#xff0c;以下内容选择其中一个做。 1. 人脸识别系统设计 (1) 人脸识别系统设计&#xff08;必做&#xff09;&#xff1a;根据…...

振弦采集仪完整链条的岩土工程隧道安全监测

振弦采集仪完整链条的岩土工程隧道安全监测 隧道工程是一种特殊的地下工程&#xff0c;其建设过程及运行期间&#xff0c;都受到各种内外力的作用&#xff0c;如水压、地震、地质变形、交通荷载等&#xff0c;这些因素都会对隧道的安全性产生影响。因此&#xff0c;对隧道的安…...

NLP实战9:Transformer实战-单词预测

目录 一、定义模型 二、加载数据集 三、初始化实例 四、训练模型 五、评估模型 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作者&#xff1a;[K同学啊] 模型结构图&#xff1a; &a…...

使用Vue.js和Rust构建高性能的物联网应用

物联网(IoT)应用是现代技术的重要组成部分&#xff0c;它们可以在各种场景中&#xff08;例如智能家居&#xff0c;工业自动化等&#xff09;提供无缝的自动化解决方案。在这篇文章中&#xff0c;我们将探讨如何使用Vue.js和Rust构建高性能的物联网应用。 1. 为什么选择Vue.js…...

idea调节文字大小、日志颜色、git改动信息

idea调节菜单栏文字大小&#xff1a; 调节代码文字大小&#xff1a; 按住ctrl滚动滑轮可以调节代码文字大小&#xff1a; 单击文件即可在主窗口上打开显示&#xff1a; idea在控制台对不同级别的日志打印不同颜色 &#xff1a; “grep console”插件 点击某一行的时候&#x…...

避免大龄程序员边缘化:如何在技术行业中保持竞争力

目录 导语持续学习和进修维护专业形象寻找适合自己的领域构建个人品牌和网络拥抱变化和创新实例结语&#xff1a; 导语 导语&#xff1a;随着科技的不断发展&#xff0c;技术行业的竞争日益激烈。对于那些年龄稍长的程序员来说&#xff0c;如何保持竞争力并避免边缘化成为了一…...

Jenkins工具系列 —— 启动 Jenkins 服务报错

错误显示 apt-get 安装 Jenkins 后&#xff0c;自动启动 Jenkins 服务报错。 排查原因 直接运行jenkins命令 发现具体报错log&#xff1a;Failed to start Jetty或Failed to bind to 0.0.0.0/0.0.0.0:8080或Address already in use 说明&#xff1a;这里提示的是8080端口号…...

华为数通HCIA-实验环境ensp简介

ensp 路由器&#xff1a;AR系列、NE系列&#xff1b; 模拟器中使用AR2220&#xff1b; 交换机&#xff1a;S系列、CE系列&#xff1b; 模拟器中使用S5700&#xff1b; 线缆&#xff1a;copper——以太网链路&#xff1b; serial——串行链路&#xff0c;在模拟器中用于模…...

SK5代理与IP代理:网络安全中的爬虫利器

一、什么是IP代理与SK5代理&#xff1f; IP代理&#xff1a; IP代理是一种允许用户通过代理服务器进行网络连接的技术。用户请求经由代理服务器中转&#xff0c;从而实现隐藏真实IP地址&#xff0c;保护用户隐私&#xff0c;并在一定程度上突破IP访问限制。常见的IP代理有HTTP…...

实战:Prometheus+Grafana监控Linux服务器及Springboot项目

文章目录 前言知识积累什么是Prometheus什么是Grafana怎样完成数据采集和监控 环境搭建docker与docker-compose安装docker-compose编写 监控配置grafana配置prometheus数据源grafana配置dashboardLinux Host Metrics监控Spring Boot 监控 写在最后 前言 相信大家都知道一个项目…...

[用go实现解释器]笔记1-词法分析

本文是《用go实现解释器》的读书笔记 ​ https://malred-blog​malred.github.io/2023/06/03/ji-suan-ji-li-lun-ji-shu-ji/shi-ti/go-compile/yong-go-yu-yan-shi-xian-jie-shi-qi/go-compiler-1/#toc-heading-6http://个人博客该笔记地址 ​github.com/malred/malanghttp:/…...

在 spark-sql / spark-shell / hive / beeline 中粘贴 sql、程序脚本时的常见错误

一个很小的问题&#xff0c;简单记录一下。有时候我们会粘贴一段已经成功运行过的SQL或程序脚本&#xff0c;但是在spark-sql / spark-shell / hive / beeline 中执行时可能会报这样的错误&#xff1a; hive> CREATE EXTERNAL TABLE IF NOT EXISTS ORDERS(> Display all…...

关于视频汇聚融合EasyCVR平台多视频播放协议的概述

视频监控综合管理平台EasyCVR具备视频融合能力&#xff0c;平台基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台既具备传统安防视频监控的能力与服务&#xff0c;也支持AI智能检测技术的接入&#xff0c;可应用在多行业领域的智能化监管场…...

三星书画联展:三位艺术家开启国风艺术之旅

7月22日&#xff0c;由广州白云区文联、白云区工商联主办的“三星书画联展”&#xff0c;在源美术馆正式开展。本次书画展展出的艺术种类丰富&#xff0c;油画、国画、彩墨画、书法等作品异彩纷呈。广东省政协原副主席、农工党省委书画院名誉院长马光瑜&#xff0c;意大利艺术研…...

在腾讯云服务器OpenCLoudOS系统中安装nginx(有图详解)

1. 创建安装目录 2. 下载、安装、编译 进入安装目录&#xff1a; cd /app/soft/nginx/ 下载&#xff1a; wget https://nginx.org/download/nginx-1.21.6.tar.gz 解压&#xff1a; tar -zxvf nginx-1.21.6.tar.gz 安装插件&#xff1a; yum -y install pcre-devel 安装…...

大数据课程E5——Flume的Selector

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Selector的概念和配置属性; ⚪ 掌握Selector的使用方法; 一、简介 1. 概述 1. Selector本身是Source的子组件,决定了将数据分发给哪个Channel。 2. Selector中提供了两种模式: …...

在线查看浏览器

随着网络的兴起&#xff0c;电影和电视剧已经成为我们生活中必不可少的乐趣。然而&#xff0c;像爱奇艺、优酷、腾讯、芒果等等这些平台&#xff0c;我们想要看好视频&#xff0c;需要开通VIP&#xff0c;虽然价格不是很高&#xff0c;但是我们能省则省啊&#xff0c;今天我就给…...

谷粒商城第七天-商品服务之分类管理下的分类的拖拽功能的实现

目录 一、总述 1.1 前端思路 1.2 后端思路 二、前端实现 2.1 判断是否能进行拖拽 2.2 收集受影响的节点&#xff0c;提交给服务器 三、后端实现 四、总结 一、总述 这个拖拽功能对于这种树形的列表&#xff0c;整体的搬迁是很方便的。但是其实现却并不是那么的简单。 …...

解决单节点es索引yellow

现象 单节点的es&#xff0c;自动创建索引后&#xff0c;默认副本个数为1&#xff0c;索引状态为yellow 临时解决 修改副本个数为0 永久解决 方法1、修改elasticsearch.yml文件&#xff0c;添加配置并重启es number_of_replicas&#xff1a;副本分片数&#xff0c;默认…...

Java虚拟机在类加载阶段都做了些什么,才使得我们可以运行Java程序

前言&#xff1a; 今天和大家探讨一道Java中经典的面试题&#xff0c;这道面试题经常出现在各个公司的面试中&#xff0c;结合周志明&#xff0c;老师的《深入理解Java虚拟机》书籍&#xff0c;本篇文章主要讲解Java类加载机制的知识。该专栏比较适合刚入坑Java的小白以及准备秋…...

华为认证 | 学HCIE,想培训需要注意啥?

HCIE&#xff08;华为认证网络专家&#xff09;是华为技术认证体系中的最高级别认证&#xff0c;对于网络工程师来说考试难度也比较高&#xff0c;一般来说&#xff0c;需要进行培训。 那么HCIE考试培训需要注意啥&#xff1f; 01 充分了解认证要求 在开始准备HCIE认证之前&a…...

这所211考数一英二,学硕降分33分,十分罕见!

一、学校及专业介绍 合肥工业大学&#xff08;Hefei University of Technology&#xff09;&#xff0c;简称“合工大”&#xff0c;校本部位于安徽省合肥市&#xff0c;是中华人民共和国教育部直属的全国重点大学&#xff0c;是国家“双一流”建设高校&#xff0c; 国家“211工…...

关于BQ27427的配置问题

EVM是TI家做的BQ27427的开发板&#xff0c;这款芯片还挺新的。 大概是这样&#xff0c;一块开发板要一千多块钱&#xff0c;使用的时候还出现了一些奇怪的问题。 配置使用的是买的盗版的EV2400&#xff0c;就是黑色的那个东西&#xff0c;使用的通信方式IIC。 TI手册上写的软件…...

试卷还原成空白卷怎么做?分享个简单的方法

在进行考试时&#xff0c;可能会填错答案或想要重新测试&#xff0c;此时需要正确擦除填写的试卷答案。下面介绍一些需要注意的事项以及正确的擦除方法。 使用橡皮擦或橡皮 正确的擦除方法是使用橡皮擦或橡皮对填写的答案进行擦除。首先&#xff0c;将橡皮擦或橡皮放置在试卷上…...

查看学校名称中含北京的用户

查看学校名称中含北京的用户_牛客题霸_牛客网 1.like select device_id,age,university from user_profile where university like %北京%; 注意虽然按实际需求&#xff0c;北京一般是排在最前面&#xff0c;即北京%&#xff0c;但是严格意义上来说&#xff0c;搜索含有北京…...

快速开发人脸识别系统Java版本

简介&#xff1a; 先说下什么是人脸识别系统&#xff1a;举个例子&#xff0c;公司门口有个人脸识别系统&#xff0c;员工站到门口&#xff0c;看着摄像头&#xff0c;大屏幕上会抓拍到你的人脸&#xff0c;然后和公司的员工照片库里的照片比对&#xff0c;比对成功就提示&…...

Reinforcement Learning with Code 【Code 1. Tabular Q-learning】

Reinforcement Learning with Code 【Code 1. Tabular Q-learning】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation o…...

解决:Uncaught (in promise) SyntaxError: “[object Object]“ is not valid JSON 问题的过程

1、问题描述&#xff1a; 其一、报错为&#xff1a; Uncaught (in promise) SyntaxError: "[object Object]" is not valid JSON 中文为&#xff1a; 未捕获&#xff08;承诺中&#xff09;语法错误&#xff1a;“[object Object]”不是有效的 JSON 其二、问题描…...