Go标准库Context

在 Go 语言中,context 包提供了一种在函数之间传递请求作用域的方法。它通常用于跨 API 边界传递取消信号、超时值、截止时间以及请求范围的数据。

一、Context 接口

context.Context 接口是 Go 语言中用于管理请求作用域的重要接口之一。它定义了一组方法,用于传递取消信号、超时值、截止时间以及请求范围的数据。

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}
  • Deadline() (deadline time.Time, ok bool)
    返回上下文的截止时间(deadline),如果没有设置截止时间,则 ok 为 false。可以用于检查上下文是否有截止时间,并获取该截止时间。

  • Done() <-chan struct{}
    返回一个通道Channel(<-chan struct{}),当上下文被取消或超时时,该通道会被关闭。可以通过监听这个通道来接收取消信号,执行相应的清理或中止操作。

  • Err() error
    返回上下文取消的原因,如果上下文没有被取消,则返回 nil。可以用于检查上下文是否已被取消,并获取取消的具体原因。

  • Value(key interface{}) interface{}
    返回与键关联的值,如果键不存在则返回nil。可以用于在请求范围内传递键值对,比如传递请求标识、用户认证信息等。

context包主要提供了两种方式创建context:

  • context.Backgroud():是上下文的默认值,所有其他的上下文都应该从它衍生(Derived)出来。
  • context.TODO():只在不确定应该使用哪种上下文时使用。

这两个函数其实只是互为别名,没有差别。

二、Contex的With系列函数

2.1 WithCancel

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

context.WithCancel函数用于创建一个带有取消功能的上下文(Context)。当调用返回的CancelFunc时,所有通过该上下文启动的goroutine都会收到一个取消信号。这通常用于需要响应外部请求取消的场景,比如HTTP长轮询或者WebSocket连接。

实际使用context.WithCancel时,你需要确保正确地处理了取消信号,并且在适当的时候调用了cancel函数,以避免资源泄漏或不必要的CPU消耗

package main

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

// 模拟一个长时间运行的任务
func longRunningTask(ctx context.Context, name string) {
	for i := 0; ; i++ {
		select {
		case <-ctx.Done(): // 检查上下文是否被取消
			return // 如果被取消,立即返回
		case <-time.After(1 * time.Second): // 每秒输出一次进度
			fmt.Printf("%s: %d
", name, i)
		}
	}
}

func main() {
	// 创建一个新的带取消功能的上下文
	ctx, cancel := context.WithCancel(context.Background())

	// 使用新创建的上下文启动任务
	go longRunningTask(ctx, "task")

	// 主线程等待5秒后取消上下文
	time.Sleep(5 * time.Second)
	cancel() // 发送取消信号

	// 为了演示,我们再等2秒钟以确保任务已经接收到了取消信号并且退出
	time.Sleep(2 * time.Second)
}

2.2 WithDeadline

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

WithDeadline函数用于创建一个带有截止时间的新的Context。这个截止时间可以用来限制操作的执行时间,当超过截止时间时,可以自动取消Context

package main

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

func main() {
	parentCtx := context.Background()
	deadline := time.Now().Add(time.Millisecond * 50)
	// 创建一个带有截止时间的新context,设置截止时间为当前时间的50毫秒之后
	ctx, cancel := context.WithDeadline(parentCtx, deadline)
	// 确保在main函数返回前取消context以释放资源
	defer cancel()

	// 模拟一个需要执行的操作,比如等待100毫秒
	go func() {
		select {
		case <-time.After(100 * time.Millisecond):
			fmt.Println("操作完成")
		case <-ctx.Done():
			fmt.Println("操作超时")
		}
	}()

	// 等待一段时间,以便观察操作是否在截止时间之前完成
	time.Sleep(time.Millisecond * 200)
}

我们设置截止时间为当前时间的50毫秒之后。接着,我们启动一个goroutine来模拟一个长时间运行的操作,通过监听ctx.Done()来判断操作是否在截止时间之前完成。在主函数结束前,我们通过defer语句调用cancel函数来确保及时释放资源。

2.3 WithTimeout

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

WithTimeout是一种用于设置操作执行的超时时间的机制,它允许你指定一个时间段,在这个时间段内如果操作没有完成,就会抛出一个超时异常或执行一个指定的回调函数。

package main

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


func myFunction(ctx context.Context, duration time.Duration) {
	select {
	case <-time.After(duration):
		fmt.Println("操作成功")
	case <- ctx.Done():
		fmt.Println("操作失败")
	}
}

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

	myFunction(ctx, 2*time.Second)
}

2.4 WithValue

func WithValue(parent Context, key, val interface{}) Context

WithValue用于创建一个带有额外值的新上下文,这个值可以在上下文中进行传递。通常情况下,WithValue方法用于将一些请求范围的值(例如请求ID、用户信息等)与上下文关联起来,以便在整个请求处理过程中进行传递和访问。

需要注意的是,在使用context.WithValue方法时,应避免直接使用内置类型string作为键,因为这可能导致潜在的键冲突问题。考虑到context.WithValue方法接受interface{}类型的键和值,如果在不同的地方使用了相同的字符串作为键,那么就会导致冲突。为了避免这种情况,建议定义自己的类型作为键

package main

import (
	"context"
	"fmt"
)

// 定义一个自定义类型作为键
type contextKey string

func processRequest(ctx context.Context) {
	// 从上下文中获取请求ID
	reqID := ctx.Value(contextKey("requestID")).(int)

	// 模拟处理请求的操作
	fmt.Printf("Processing request with ID %d\n", reqID)
}

func main() {
	// 创建一个带有请求ID的上下文
	ctx := context.WithValue(context.Background(), contextKey("requestID"), 12345)

	// 处理请求
	processRequest(ctx)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/773942.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html三级菜单

示例 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Menu Example</title> <link re…

工作效率飞跃提升

Hey小伙伴们&#x1f44b;&#xff0c;今天我要来给大家种草几款让我效率翻倍的超实用工具&#x1f6e0;️&#xff01;如果你也常常感觉时间不够用&#xff0c;这些小帮手绝对能让你事半功倍哦✨&#xff01; 1️⃣ 亿可达 — 软件连接器&#x1f517; 作为一款自动化工具&am…

SVN回退版本

我是直男, 所以, 就直接进入主题了 先本地备份要重新上传的代码文件 回退版本 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ → 然后提交刚刚回退的文件(别忘了) ← ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 到这里…

【Python机器学习】处理文本数据——将文本数据表示为词袋

用于机器学习的文本有一种最简单的方法&#xff0c;也是最有效且最常用的方法&#xff0c;就是使用词袋表示。使用这种表示方法时&#xff0c;我们舍弃了输入文本中的大部分结构&#xff0c;比如章节、段落、句子和格式&#xff0c;只计算语料库中&#xff0c;只计算语料库中每…

Elasticsearch实战教程:如何使用集群索引数据来进行统计多个数据?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 Elasticsearch聚合查询是一种强大的工具&#xff0c;允许我们对索引中的数据进行复杂的统计分析和计算。本文将详细解释一…

为何整个 AI 领域都朝着 AI Agents 这一方向发展?

编者按&#xff1a; 当前大热的大语言模型和检索增强生成模型&#xff0c;虽然在语言理解和内容生成方面取得了突破性的进展&#xff0c;但仍然存在诸多限制。它们缺乏根据目标导引行为、持续学习和与环境交互的能力&#xff0c;难以应对复杂多变的现实场景需求。 今天为大家带…

国信华源全力守护湖南水库安全,汛期坚守岗位

连日来&#xff0c;湖南省遭受持续强降雨侵袭&#xff0c;部分地区暴雨倾盆&#xff0c;山塘河库水位急剧上升&#xff0c;防汛形势极为严峻。面对这场防汛大考&#xff0c;北京国信华源公司迅速响应&#xff0c;技术团队以高度的责任感和使命感&#xff0c;全力投入防汛减灾工…

ASP.NET Core Blazor 5:Blazor表单和数据

本章将描述 Blazor 为处理 HTML 表单提供的特性&#xff0c;包括对数据验证的支持。 1 准备工作 继续使用上一章项目。   创建 Blazor/Forms 文件夹并添加一个名为 EmptyLayout.razor 的 Razor 组件。本章使用这个组件作为主要的布局。 inherits LayoutComponentBase<div …

vue表单增加合计

vue表单增加合计&#xff0c;有两种方式&#xff1a; 第一种前端获取所有数据&#xff1a; 将 show-summary 设置为true就会在表格尾部展示合计行。 默认情况下&#xff0c;对于合计行&#xff0c;第一列不进行数据求合操作&#xff0c;而是显示「合计」二字&#xff08;可通…

LeetCode刷题记录:(14)文本左右对齐

遇见困难题不要怕&#xff0c;说不定就是一个简单模拟题 . 执行用时 相关企业 leetcode 传送通道 class Solution {List<String> ans new ArrayList<>(); // 本题答案列表int[] lens; // 记录每个单词长度&#xff0c;方便后续补齐空格操作int maxRowLen; // 替代…

sql业务场景分析思路参考

1、时间可以进行排序&#xff0c;也可以用聚合函数对时间求最大值max&#xff08;时间&#xff09; 例如下面的例子&#xff1a;取最晚入职的人&#xff0c;那就是将入职时间倒序排序&#xff0c;然后limit 1 表&#xff1a; 场景&#xff1a;查找最晚入职员工的所有信息 se…

【数据集】中国农田栅格数据CACD(1986-2021)

中国农田栅格数据(1986-2021) 数据概述数据下载参考精确、详细和及时的耕地范围信息对于保障食品安全和环境可持续性至关重要。然而,由于农业景观的复杂性以及缺乏足够的训练样本,要在大范围地理区域内高空间和时间分辨率下监测耕地动态仍然具有挑战性,特别是对于农业土地…

抖音本地生活服务商入驻要求中暗含哪些信息?入局要点都在里面了!

随着抖音外卖的正式开放&#xff0c;许多创业者对于做抖音本地生活服务商的意向愈发强烈&#xff0c;抖音本地生活服务商入驻要求及相关话题更是在多个创业者群内被翻来覆去地讨论&#xff0c;且多次刷屏。 而就抖音目前在本地生活市场的布局来看&#xff0c;其主要的重心还是…

哪里还可以申请免费一年期的SSL证书?

目前&#xff0c;要申请免费一年期的SSL证书&#xff0c;选项较为有限&#xff0c;因为多数供应商已转向提供短期的免费证书&#xff0c;通常有效期为90天。不过&#xff0c;有一个例外是JoySSL&#xff0c;它仍然提供一年期的免费SSL证书&#xff0c;但是只针对教育版和政务版…

【人工智能】--强化学习(2.0)

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a; 专业知识 文章目录 &#x1f349;强化学习与有监督学习的区别 &#x1f348;数据特点 &#x1f348;学习目标 &#x1f348;反馈机制 &#x1f348;策略…

如何在word中敲出可以点击打勾和取消打勾的方框呢?

文章目录 要解决的问题网上出现的几种不可行的方案发现解决措施 要解决的问题 在word中敲出 点击就可以打对勾和取消对钩的方框 网上出现的几种不可行的方案 插入-> 符号&#xff0c;此方法打出的方框是fixed的&#xff0c;不是我想要的可以自己自主打勾和不打勾的方式。 …

Python获取QQ音乐歌单歌曲

准备工作 歌单分享的url地址 比如&#xff1a; https://i.y.qq.com/n2/m/share/details/taoge.html?hosteuinoKvzoK4l7evk7n**&id9102222552&appversion130605&ADTAGwxfshare&appshareiphone_wx 代码实现 def mu(share_url):share_url share_url.split(id…

CFS三层内网渗透——外网打点(一)

目录 外网打点 先爆破一下看看有没有啥可进攻路径 尝试那个可疑的路径发现是thinkphp这个框架&#xff0c;同时也知道了版本&#xff0c;那就nday打吧 写入php ​编辑写入php成功&#xff0c;简简单单nday拿下​编辑 蚁剑rce尝试链接 打点成功 外网打点 先爆破一下看看有…

Odoo 16 采购仪表盘概述

Odoo 16 的高级采购管理系统可让您轻松跟踪采购订单、定义产品、管理供应商和准备产品/服务。您可以在采购模块中管理与产品采购相关的所有功能。此模块还允许您跟踪采购订单和报价请求。将采购模块的功能与其他 Odoo 16 模块&#xff08;如会计、库存、销售和发票&#xff09;…

用免费的可视化工具制作3D智慧城市大屏,融合数字孪生,引领数据升级

在如今数据驱动的时代&#xff0c;越来越多的场景中都有可视化大屏的身影&#xff0c;许多企业和政府部门也从常规的二维看板渐渐地转向更加炫酷&#xff0c;立体的3D可视化大屏。3D可视化大屏成为了展示复杂数据、实时监控业务动态的重要工具。本文将详细介绍如何使用免费的数…