golang开发 深入理解 context
context的历史
context包在Go 1.7版本正式加入Go标准库。在加入之前我们看看Go团队核心成员Sameer Ajmani在2014年发表的一篇关于context介绍博客,地址:https://go.dev/blog/context 下面是介绍的翻译。
在Go服务器中,每个传入的请求都在自己的goroutine中处理。请求处理程序经常启动额外的goroutine来访问后端,如数据库和RPC服务。处理请求的goroutine集合通常需要访问特定于请求的值,例如最终用户的身份、授权令牌和请求的截止日期。当一个请求被取消或超时时,所有处理该请求的goroutine都应该迅速退出,这样系统就可以回收它们正在使用的任何资源。
在Google,我们开发了一个 context 包,可以轻松地将请求范围内的值、取消信号和截止日期跨API边界传递给处理请求所涉及的所有goroutine。该软件包作为上下文公开提供。
可以看到介绍里面主要说的是,应用中怎么控制大量的goroutine退出释放资源、请求范围内怎么传值,也就是说,context的引入主要是为了解决这两个问题。
context的基本使用
context初始化的方法有五个,一个是main goroutine 初始化,一个主要是是用来传值的,经常使用的就三个。
未超时的时候,执行取消,依赖取消函数
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "main", "main-value")
ctx1,cancel := context.WithDeadline(ctx, time.Now().Add(3*time.Second))
go cancelFunc(ctx1)
//取消函数
cancel()
time.Sleep(time.Duration(5*time.Second))
}
执行结果
main-param main-value
退出协程
超时的时候执行结果,超过三秒的超时时间,依赖超时时间
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "main", "main-value")
ctx1,_ := context.WithDeadline(ctx, time.Now().Add(3*time.Second))
go cancelFunc(ctx1)
time.Sleep(time.Duration(5*time.Second))
}
执行结果
main-param main-value
1秒
1秒
1秒
退出协程
看注释和执行流程,基本能理解,main函数调用cancel就能取消正在执行的goroutine协程。WithDeadline和WithTimeout 除过可以通过调用取消函数,还可以通过设置超时时间点和时间段取消goroutine的执行。
context如何控制多个goroutine,如何传值给多个goroutine
看图示,root context控制着所有的goroutine,context1控制着 goroutine2 goroutine3 goroutine4 goroutine5 goroutine6 goroutine7,context2 控制着goroutine4 goroutine5,context3 控制着goroutine6 goroutine7。
使用图示的goroutine 编写测试代码
package main
import (
"context"
"fmt"
"time"
)
func func1(ctx context.Context) {
fmt.Println("func1-main-param", ctx.Value("main"))
ctx1 := context.WithValue(ctx, "func1-param", "func1-value")
go func2(ctx1)
select {
case <-ctx1.Done():
fmt.Println("goroutine 1 exit")
}
}
func func2(ctx context.Context) {
fmt.Println("func2-main-param", ctx.Value("main"))
fmt.Println("func2-func1-param", ctx.Value("func1-param"))
ctx2, _ := context.WithCancel(ctx)
go func4(ctx2)
go func5(ctx2)
select {
case <-ctx2.Done():
fmt.Println("goroutine 2 exit")
}
}
func func4(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("goroutine 4 exit")
}
}
func func5(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("goroutine 5 exit")
}
}
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "main", "main-value")
ctx,cancel := context.WithCancel(ctx)
go func1(ctx)
cancel()
time.Sleep(time.Duration(5*time.Second))
}
运行结果
func1-main-param main-value
goroutine 1 exit
func2-main-param main-value
func2-func1-param func1-value
goroutine 2 exit
goroutine 5 exit
goroutine 4 exit
可以看到最终实现结果和场景,跟Sameer Ajmani在博客描述的是一样的,context的出现主要两个作用,控制 goroutine,goroutine之间传值。
golang开发 深入理解 context的更多相关文章
- 全面理解Context
出处:http://blog.csdn.net/lmj623565791/article/details/40481055,本文出自:[张鸿洋的博客] 本文大多数内容翻译自:http://www.do ...
- grpc(3):使用 golang 开发 grpc 服务端和client
1,关于grpc-go golang 能够能够做grpc的服务端和client. 官网的文档: http://www.grpc.io/docs/quickstart/go.html https://g ...
- go笔记--几个例子理解context的作用
目录 go笔记--几个例子理解context的作用 context interface 先看一个简单的例程 context的作用 contxt相关函数 go笔记--几个例子理解context的作用 经 ...
- 十分钟学会Golang开发gRPC服务
gRPC是Google发起的一个开源RPC框架,使用HTTP/2传输协议,使用Protocol Buffers编码协议,相比RESTful框架的程序性能提高不少,而且当前流行的编程语言基本都已经支持. ...
- 用golang开发系统软件的一些细节
用golang开发系统软件的一些细节 作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 (本文的pdf版本) ...
- 使用golang 开发的 andriod应用
最近在捣鼓一个东东,就是使用golang开发andriod应用.说起来简单操作起来还挺麻烦,中间又学习了很多东西.比如ubuntu,docker,angular,ionic,jquery mobile ...
- golang开发android环境搭建_window
golang开发android环境搭建介绍 一 安装依赖软件: git:版本管理 go: go开发环境(版本>=1.5),可直接下载window版的go安装包. android studio: ...
- Android-5 理解context
context -- 用来访问全局信息 Application用途 Application生命周期 深入理解 Context http://blog.csdn.net/z1074971432/arti ...
- Windows下visual studio code搭建golang开发环境
Windows下visual studio code搭建golang开发环境 序幕 其实环境搭建没什么难的,但是遇到一些问题,主要是有些网站资源访问不了(如:golang.org),导致一些包无法安装 ...
- go get报错unrecognized import path “golang.org/x/net/context”…
今天安装gin框架,首先下载gin,命令如下:go get github.com/mattn/go-sqlite3 结果报错: package golang.org/x/net/context: un ...
随机推荐
- flomo 窗口置顶 - 通用方法 autohotkey
需求 开网页的时候需要记录一些东西 想一直显示 操作 要安装 https://www.autohotkey.com/ 创建个 .ahk 文件 运行下 快捷键是 alt+小键盘8 ;置顶当前窗口 !Nu ...
- 基于ADS1292芯片的解决方案之源码解析
接口解析 A 该芯片和主控使用的是SPI接口通信的. SPI接口一般有四根线,确保四根线准确连接是对的. B 该芯片可以有中断模式数据触发,所以,主控mcu需要有外部中断处理流程. //DRDY中断 ...
- 用python进行二进制bin文件合并
一 基本概念 bin文件合并是嵌入式中常用的,这里给一个实例. 二 实例分析 import os import argparse import hashlib offset1 = 0x0010000 ...
- python 判断bytes是否相等的几种方法
一 前言: python判断bytes是否相等,一般要用到这几种方法:is,==,operator.下面做几个例子让大家看一下. 二 正文: 1 相等方法: test1=b'0xab' test2=b ...
- Android Studio批量打渠道包
原文: Android Studio批量打渠道包 - Stars-One的杂货小窝 公司项目渠道包越来越大,每次发版本都是开发人员打包,研究了下如何批量打渠道包,记录过程 步骤 1.gradle配置 ...
- 【Linux】Git 安装最新版
# 移除旧版 Git yum remove git # 安装依赖包 yum install curl-devel expat-devel gettext-devel openssl-devel zli ...
- 使用 LogProperties source generator 丰富日志
Nuget包 Microsoft.Extensions.Telemetry.Abstractions 包含的新的日志记录source generator,它支持使用[LogProperties]将整个 ...
- django(Ajax、自定义分页器、form组件)
一.Ajax 1 概述 异步提交局部刷新 例子:github注册 动态获取用户名实时的跟后端确认并实时展示到前端(局部刷新) 朝后端发送请求的方式 1.浏览器地址栏直接输入url回车 GET请求 2. ...
- 工作记录:Vue3.0新特性
简单对比 Vue2.x 与 Vue3.x 响应式 Vue2 使用Object.defineProperty劫持对象的属性 Vue3 使用Proxy 直接代理对象 由于Object.defineProp ...
- 运行xxl-job,整合xxl-job至jeecg-boot项目
1.前言:xxl-job是一个分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并接入多家公司线上产品线,开箱即用. 源码仓库地址:https://gitee.co ...