Go的并发如何配合上下文(ctx Context)使用? [_]~( ̄▽ ̄)~* Go相关

2023-05-16

文章目录

  • 上下文处理
    • 创建上下文
    • 上下文继承
      • 线程安全

说明: 上下文的英文是context, 其英文简写约定俗成是 ctx

上下文处理

上下文在go中有一个约定俗成的写法ctx, 如果你用过python应该知道self, 这是python类初始化的一个对象, 在python的类中任何函数都可以去读取和使用它, 并且会把它当作第一个参数传入。而ctx也有点类似self, 他也是一个约定俗成的叫法, 并没有强制性, 并且如果使用,一般也是作为函数的第一个变量传入, 一般我们在go的主进程中生成上下文, 并且所有需要的go程都可以获取上下文。

创建上下文

在Go中, 上下文除了传递消息对象外, 还有一个非常重要的作用, 就是用它来传递取消关闭信号。特别是在众多Go程中, 我们可以用上下文来同时控制其的运行状态(开启或结束)。

上下文中, 内置了四个函数, 可以对已有的上下文进行操作

  1. Deadline() (过期时间 time.Time, ok bool): 查看是否有过期时间, 如果有就返回过期时间
  2. Done() <-chan struct{}: 用于做退出判断, 如果过期时间或者持续时间结束, 或手动执行CancelFunc, 则会向此处传入一个空结构体。
  3. Err() error: 用来解释退出的原因。
  4. Value(key any) any: 用来读取上下文中的值。

我们常用创建上下文的方法常用的有五种

  1. context.Background() Context: 一般我们最底层创建上下文会用到这个, 可以看出获取一个空上下文的方法。它及不包含信息, 也没有传递关闭信号的功能。
  2. context.WithCancel(父级上下文 Context) (Context, CancelFunc): 这算是比较常规的上下文, 他会返回当前的上下文和一个取消函数。
func 常规上下文() {
	上下文, 常规取消 := context.WithCancel(空上下文)
	获取过期时间, ok := 上下文.Deadline()
	if ok {
		fmt.Println("过期时间为:", 获取过期时间)
	} else {
		fmt.Println("未设置过期时间")
	}
	for i := 0; i < 2; i++ {
		select {
		case <-time.After(time.Second):
			常规取消()
			fmt.Println("执行取消")
		case 取消信息 := <-上下文.Done():
			fmt.Println("已取消:", 取消信息, 上下文.Err())
		}
	}
}

func main() {
	fmt.Println("开始时间: ", time.Now())
	常规上下文()
}

在这里插入图片描述
3. context.WithDeadline(父级上下文 Context, 过期时间 time.Time) (Context, CancelFunc): 这种上下文可以设置一个过期时间, 在到达过期时间的时候让相关进程结束, 比如我们可以给一个用户的登录信息放在上下文中, 并设置过期时间, 设置过过期时间的上下文可以从上下文.Deadline()获取到截止日期

func 过期上下文(过期时间 time.Time) {
	上下文, 主动取消 := context.WithDeadline(空上下文, 过期时间)
	defer 主动取消()
	for {
		select {
		case <-time.After(1 * time.Second):
			获取过期时间, ok := 上下文.Deadline()
			if ok {
				fmt.Println("过期时间为:", 获取过期时间)
			}
			fmt.Println("正常执行中!")
		case <-上下文.Done():
			fmt.Println("已取消:", 上下文.Err())
			return
		}
	}
}

func main() {
	fmt.Println("开始时间: ", time.Now())
	时间 := time.UnixMicro(time.Now().UnixMicro() + (time.Second.Microseconds() * 3))
	过期上下文(时间)
}

在这里插入图片描述
4. context.WithTimeout(父级上下文 Context, 持续时间 time.Duration) (Context, CancelFunc): 这样用法和上述过期时间类似, 只不过把过期时间改为了倒计时的形式, 这种方法通用可以从上下文.Deadline()获取到截止日期

func 超时上下文(倒计时 time.Duration) {
	上下文, 取消 := context.WithTimeout(空上下文, 倒计时)
	上下文.Deadline()
	defer 取消()
	for {
		select {
		case <-time.After(1 * time.Second):
			获取超时时间, ok := 上下文.Deadline()
			if ok {
				fmt.Println("超时时间: ", 获取超时时间)
			}
			fmt.Println("正常执行中")
		case <-上下文.Done():
			fmt.Println(上下文.Err())
			return
		}
	}
}

func main() {
	fmt.Println("开始时间: ", time.Now())
	计时 := 3 * time.Second
	超时上下文(计时)
}

在这里插入图片描述
5. context.WithValue(父级上下文, 键, 值 any) Context: 用于上下文传递信息保存键值对, 但要注意的是, 上下文一般传播范围会非常广, 为了尽量节省资源, 务必只传入一些必要的信息, 一些可选信息就没有必要进行传播了。比如用户ID, 用户key, 系统os类型等程序启动后基本不会变更的数据, 运行时参数的各种杂项数据是不推荐放入上下文的。

func 传值上下文(, 值 any) {
	上下文 := context.WithValue(空上下文,,)
	fmt.Println("当前上下文的键为: ", 上下文.Value())
}

func main() {
	fmt.Println("开始时间: ", time.Now())
	传值上下文("我是键", "寻觅")
}

PS: 除此之外, 还有一个context.TODO() Context 这个方法在代码层面和context.Background() Context实现的东西是一模一样的, 但TODO主要是用来占位的, 可以看作为一个占位符, 而Background则是可以看成一个空的上下文, 用来做我们的创建模板用的。

上下文继承

Go上下文的继承很好理解, 父级会影响子级, 父级一旦关闭, 所有子级也都会随之关闭, 子集的值会覆盖父级, 但子集的过期时间和持续时间是会被父级影响的。
但上下文关闭不会影响使用Value(key any) any取值, 父级上下文关闭后, 子集上下文还是可以正常取值

func 上下文传递测试() {
	上下文1, 取消 := context.WithCancel(空上下文)
	defer 取消()
	上下文2 := context.WithValue(上下文1, "测试键", "上下文1的键")
	上下文3, _ := context.WithTimeout(上下文2, 5*time.Second)
	for {
		select {
		case <-time.After(2 * time.Second):
			fmt.Println("上下文1取消前的上下文3: ", 上下文3.Value("测试键"))
			取消()
			fmt.Println("上下文1 已被取消")
			fmt.Println("上下文1取消前的上下文3: ", 上下文3.Value("测试键"))
		case <-上下文3.Done():
			fmt.Println("上下文1: ", 上下文1.Err(), <-上下文1.Done())
			fmt.Println("上下文2: ", 上下文2.Err(), <-上下文2.Done())
			fmt.Println("上下文3: ", 上下文3.Err(), <-上下文3.Done())
			return
		}
	}
}

func main() {
	fmt.Println("开始时间: ", time.Now())
	上下文传递测试()
}

在这里插入图片描述

线程安全

这里的线程安全是指, 多个Go程同时操作上下文, 进行读写等操作, 是否会出现异常。首先, Go的上下文并没有提供一个写Set接口, 而只有一个类似读Value(键)的接口, 所有数据的写入操作都在上下文定义的那一刻就决定了。
想要变更数据, 就只能通过创建子上下文, 在子上下文中添加新值, 或覆盖老值, 但父上下文中的值是不会改变的。不只是父子上下文, 所有上下文中的数据都是独立的, 互不影响的

func 创建上下文(上下文 context.Context,string) context.Context {
	for {
		_ = context.WithValue(上下文, "测试键",)
	}
}

func 上下文线程安全() {
	上下文 := context.WithValue(context.Background(), "测试键", "---")
	go 创建上下文(上下文, "+++")
	go 创建上下文(上下文, "***")
	go func() {
		for {
			fmt.Println(上下文.Value("测试键"))
			time.Sleep(time.Second)
		}
	}()
	time.Sleep(time.Second * 10)
}

func main() {
	fmt.Println("开始时间: ", time.Now())
	上下文线程安全()
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go的并发如何配合上下文(ctx Context)使用? [_]~( ̄▽ ̄)~* Go相关 的相关文章

  • 人工智能如何可以思考?

    近日在给同事讲人工智能的时候 xff0c 提到当数据量不够的时候 xff0c 必要时需要加入人工工程 xff0c 引导计算机 归纳 一些知识 xff0c 毕竟计算机智能比起人类智能 xff0c 最大的缺陷可能在于不懂得 举一反三 换句话说
  • bag文件内topic对应的frame_id查看指令

    启动ROS roscore 运行数据集 span class token comment 数据集小的话 xff0c 建议慢速播放 span rosbag play xxx span class token punctuation span
  • GPS数据类型(ROS)

    文章目录 一 传感器分类二 作用三 系统组成四 位置表示五 数据格式六 ROS中GPS数据格式sensor msgs NavSatFixROS中GPS数据主要包含这四类 xff0c 分别是gps 裸数据ros封装 xff0c 位置 xff0
  • cmake使用教程

    CMakeLists txt文档编写以及packsge xml文档介绍 CMakeLists txt文档一 cmake minimum required命令二 CMake中的编译类型三 cmake编译选项 xff08 与2对应 xff09
  • 四旋翼无人机飞控系统设计(闭环控制系统)

    对于一个简单的飞控程序来说 xff0c 控制器是它最核心的部分 xff0c 这里主要与大家讨论控制系统的基本理论知识 xff08 自控大佬请绕道 xff09 xff0c 包括控制系统概念 闭环控制系统的原理 下篇将侧重包含pid控制算法的具
  • 针对frame_id和child_frame_id的理解

    ros基础必看之各个frame的理解 ROS坐标系统 xff0c 常见的坐标系和其含义 ROS中TF 坐标系转换 原理与使用
  • IMU预积分学习

    IMU预积分学习 一 IMU状态传递方程 一 IMU状态传递方程 几种不同的表达形式 xff1a 1 lio mapping xff1a 参考大佬 xff1a lio mapping 及 VINS Mono代码及理论推导 xff08 2 x
  • Python3 内置模块 - os

    方法名说明os access判断文件权限os chdir改变当前工作目录os chmod file 修改文件权限os execvp 启动一个新进程os execvp 执行外部程序脚本 xff08 Uinx xff09 os fork 获取父
  • AttributeError: module 'tornado.web' has no attribute 'asynchronous'解决方法

    AttributeError module tornado web has no attribute 39 asynchronous 解决方法 今天看tornado异步时发现的错误 xff0c 查了一下 xff0c 原来tornado6以后
  • 【STM32项目】- 人体检测(体温、心率、心跳、跌倒检测)

    STM32人体检测 xff08 体温 心率 心跳 跌倒检测 xff09 43 zigbee 笔者前言 在闲鱼有缘结识的一个哥们 xff0c 帮助做的基于STM32人体检测系统 xff0c 我负责硬件程序开发设计 xff0c 哥们负责客户端服
  • ESP32 之 esp32-cam wifi拍照传图系统1

    文章目录 ESP32 之 esp32 cam wifi拍照传图系统1 效果演示2 材料准备3 原理图接线4 下载代码 ESP32 之 esp32 cam wifi拍照传图系统 1 效果演示 2 材料准备 ESP32 camUSB转TTL按钮
  • ESP32 之 esp32-cam wifi拍照传图系统2

    ESP32 之 esp32 cam wifi拍照传图系统 补充说明 ESP32 CAM总结 一 ESP32初识 ESP32 CAM模组的核心芯片 xff1a ESP32 S 模块是一款超小体积的多功能通用型 802 11b g n WiFi
  • 【PX4 飞控二次开发】第一个程序 打印输出-模拟

    第一个程序 1 编写任务代码 Cmake文件2 编译 1 编写任务代码 Cmake文件 span class token operator span span class token operator span PIX4 span clas
  • 【PX4 飞控二次开发】UORB 发布及订阅自定义

    UORB测试 一 添加msg1 创建 msg文件2 Cmakelists txt修改3 编译错误4 编译成功 二 发布及订阅主题1 添加代码2 修改cmake3 再次编译 一 添加msg 1 创建 msg文件 span class toke
  • 【PX4 飞控二次开发】自制ESP8266WIFI数传

    ESP8266数传模块 一 简介二 下载烧录固件1 下载MavLink ESP8266固件2 烧录 三 连线四 配置ESP8266五 连接WIFI Bridge 一 简介 ESP8266是一款低成本 xff0c 易于使用的Wi Fi模块 x
  • 四旋翼无人机飞控系统设计(PID控制算法)

    PID控制算法 PID控制器是一个结构简单并且成熟稳定的控制器 xff0c 在工业上应用广泛 包括比例 xff08 Proportion xff09 积分 xff08 Integral xff09 微分 xff08 Differential
  • 树莓派入门-环境搭建

    树莓派环境搭建 一 修改文件1 1系统安装1 2添加修改文件 二 更换源加速2 1修改sources list2 2修改raspi list2 3更新系统 三 配置系统3 1摄像头 VNC3 2安装TFTP服务3 3固定IP3 4分辨率修改
  • STM32实战-串口通信方式汇总

    STM32实战 串口通信方式汇总 1 串口基本概念1 1 串口通讯 Serial Communication 1 2 串口通讯的数据格式1 3 通讯方式1 4 串口物理链路形式1 5 同步通信和异步通信 2 STM32 串口配置2 1 US
  • 【STM32项目】老人健康跌倒检测系统实现

    目录 基于STM32老人跌倒检测系统实现一 功能展示二 硬件方案2 1 模组选型2 2 硬件设计 三 软件实现3 1功能概述3 2软件平台 四 实现原理 xff08 持续更新 xff09 3 1 跌倒算法实现3 2 心率血氧检测3 3 红外
  • Linux常用提权方法 (゚益゚メ) 渗透测试

    文章目录 简介常用命令汇总 靶机环境Linux提权方法Linux提权漏洞利用脏牛 Dirty COW CVE 2016 5195漏洞CVE 2019 7304漏洞CVE 2019 13272漏洞CVE 2021 3156漏洞 Linux环境

随机推荐