当前位置:网站首页>Go Context基本使用
Go Context基本使用
2022-08-10 14:31:00 【EthanLeo】
Go Context的基本使用
此文章主要是用来介绍一下golang里面context的使用,因为之前一直不太清楚context的用法,以及context的一些基本特性。
Context的使用场景
Context的功能可以从两个方面去体现:
发送终止信号去提供给方法 传递一些公用的数据给多个方法
为什么需要取消操作(终止信号)
简单来说,我们需要一些终止信号,来告诉我们的程序去停止进行一些不必要的工作。
用一个简单的例子来说明:

从客户端发送请求到程序处理再到数据库中,正常流程如下图所示

但是当客户端发送请求后,如果断开链接,那么正常情况下后序的数据库查询操作应该停止,如果没有任何中止信号那么程序会继续执行,但是正常的情况是需要终止继续操作

所以我们就知道为什么需要终止信号了
Go中Context终止信号发送方式
在go中有两个方面去实现终止信号
监听终止事件 发布终止事件
监听终止事件
Context提供了一个Done()的方法,该方法会返回一个channel,每次监听到上下文发送了取消事件的时候,都发送一个空的struct{}到该管道中,所以为了监听到取消事件,我们需要等待 <-ctx.Done()传递的信号量。
func TestListeningCancel(t *testing.T) {
// 测试方法
// 浏览器打开localhost:8000
// 两秒之后会返回request processed
// 如果发送请求后立刻断开那么 ctx.Done() 能够收到信号 执行中断
http.ListenAndServe(":8000", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
fmt.Fprint(os.Stdout, "processing request\n")
select {
case <-time.After(2 * time.Second):
// 2秒后要是收到信号
// 说明请求被执行
w.Write([]byte("request processed"))
case <-ctx.Done():
// 如果请求被取消 输出请求被取消
fmt.Fprint(os.Stderr, "request cancelled")
}
}))
}
发送终止事件
如果你有一个操作要被取消,那么你需要通过上下文发送一个取消事件
我们可以通过Context包里的内置方法WithCancel(),该方法会返回一个context和一个function
ctx,fn :=context.WithCancel()
// 这个方法是假设一个操作失败
func Operation1(ctx context.Context)error{
time.Sleep(100 *time.Millisecond)
return errors.New("failed")
}
func Operation2(ctx context.Context){
select {
case <-time.After(500*time.Millisecond):
fmt.Println("done")
case <-ctx.Done():
fmt.Println("halted operation2")
}
}
func TestEmittingCancel(t *testing.T){
// 创建一个新的context
ctx := context.Background()
// 通过一个原始创建的ctx 将其包装成为一个新的,带有取消方法的ctx
ctx, cancel := context.WithCancel(ctx)
// 执行上面两个操作 ,让一个操作是在一个go routine中
go func() {
err := Operation1(ctx)
if err!=nil{
cancel()
}
}()
// 执行2操作的时候一样用同样的ctx
Operation2(ctx)
}
该示例就是演示,go有一个协程发送了取消的信号的时候,监听相同context的线程也可以收到信号,并执行操作
超时取消
context包也提供了一个超时取消的方法context.WithTimeout,该方法会在倒计时结束之后自动发送取消信号
func TestCancelWithTimeout(t *testing.T){
// 创建一个空ctx
ctx := context.Background()
// 设置超时时间
cxt, _ := context.WithTimeout(ctx, 1*time.Millisecond)
// 创建一个请求 访问谷歌
req, _ := http.NewRequest(http.MethodGet, "http://baidu.com", nil)
// 将带有取消方法的ctx和请求关联
req = req.WithContext(cxt)
client := &http.Client{}
res, err := client.Do(req)
if err!=nil{
fmt.Println("Request failed:", err)
return
}
fmt.Println("Response received, status code:", res.StatusCode)
}
Context Values
当有多个操作需要用到同一个value的时候,context也提供了对应的方法,可以让多个执行方法获取到值,使用这样的方法进行值传递可以保证对改值的操作是线程安全的
const keyID = "id"
func TestContextWithValue(t *testing.T) {
rand.Seed(time.Now().Unix())
ctx := context.WithValue(context.Background(), keyID, rand.Int())
operation1(ctx)
}
func operation1(ctx context.Context) {
log.Println("operation1 for id:", ctx.Value(keyID), " completed")
operation2(ctx)
}
func operation2(ctx context.Context) {
log.Println("operation2 for id:", ctx.Value(keyID), " completed")
}
以上就是context的一些基本操作,后序还需要进入深度研究
边栏推荐
- 无线网络、HTTP缓存、IPv6
- 镜像瘦身:每一层都不能放过
- Unfinished mathematics test paper ----- test paper generator (Qt includes source code)
- PyTorch multi-machine multi-card training: DDP combat and skills
- PEST 分析法
- 正则表达式(包含各种括号,echo,正则三剑客以及各种正则工具)
- Send a post request at the front desk can't get the data
- 蓝帽杯半决赛火炬木wp
- 这一次,话筒给你:向自由软件之父斯托曼 提问啦!
- 图式图例规范尺寸
猜你喜欢
随机推荐
leetcode 739. Daily Temperatures 每日温度(中等)
numpy.meshgrid()理解
微信扫码登陆(1)—扫码登录流程讲解、获取授权登陆二维码
从洞察到决策,一文解读标签画像体系建设方法论
电脑重装系统提示activex部件不能创建对象如何解决
MQTT服务器搭建
PyTorch 多机多卡训练:DDP 实战与技巧
BCG库简介
Summary of Force Buckle Solution 640 - Solving Equations
快速了解大端模式和小端模式
池化技术有多牛?来,告诉你阿里的Druid为啥如此牛逼!
机器学习总结(一)
等保2.0一个中心三重防护指的是什么?如何理解?
1004 (tree array + offline operation + discretization)
中学数学建模书籍及相关的视频等(2022.08.09)
Error: Rule can only have one resource source (provided resource and test + include + exclude)
使用决策树对鸢尾花进行分类
MySQL - 数据库的存储引擎
静态变量存储在哪个区
丁香园









![[JS Advanced] Creating sub-objects and replacing this_10 in ES5 standard specification](/img/3e/14a1d7c2837c896eaa0ca625eaa040.png)