context 上下文管理

context 翻译过来就是上下文管理,主要作用有两个:

  • 控制 goroutine 的超时
  • 保存上下文数据

WithTimeout

通过下面的一个简单的 http 例子进行理解

demo:

package main

import (
"fmt"
"time"
"net/http"
"context"
"io/ioutil"
) type Result struct{
r *http.Response
err error
} func process(){
ctx,cancel := context.WithTimeout(context.Background(),2*time.Second)
defer cancel()
tr := &http.Transport{}
client := &http.Client{Transport:tr}
c := make(chan Result,1)
req,err := http.NewRequest("GET","http://www.google.com",nil)
if err != nil{
fmt.Println("http request failed,err:",err)
return
}
// 如果请求成功了会将数据存入到管道中
go func(){
resp,err := client.Do(req)
pack := Result{resp,err}
c <- pack
}() select{
case <- ctx.Done():
tr.CancelRequest(req)
fmt.Println("timeout!")
case res := <-c:
defer res.r.Body.Close()
out,_:= ioutil.ReadAll(res.r.Body)
fmt.Printf("server response:%s",out)
}
return } func main() {
process()
}

WithValue

再写一个 context 保存上下文

demo:

package main

import (
"context"
"fmt"
) func add(ctx context.Context,a,b int) int {
traceId := ctx.Value("trace_id").(string)
fmt.Printf("trace_id:%v\n",traceId)
return a+b
} func calc(ctx context.Context,a, b int) int{
traceId := ctx.Value("trace_id").(string)
fmt.Printf("trace_id:%v\n",traceId)
//再将ctx传入到add中
return add(ctx,a,b)
} func main() {
//将ctx传递到calc中
ctx := context.WithValue(context.Background(),"trace_id","123456")
ret := calc(ctx,20,30)
fmt.Printf("%d", ret)
}

运行结果:

trace_id:123456
trace_id:123456
50

WithCancel 

关于 context 官网上也有一个例子非常有用,用来控制开启的 goroutine 的退出释放

demo:

package main

import (
"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 := 1
go func() {
for {
select {
case <-ctx.Done():
return // returning not to leak the goroutine
case dst <- n:
n++
}
}
}()
return dst
} ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished consuming integers for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
break
}
}
}

WithDeadline

关于官网中的 WithDeadline 演示的代码例子

demo:

package main
import (
"context"
"fmt"
"time"
) func main() {
d := time.Now().Add(50 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), d) // Even though ctx will be expired, it is good practice to call its
// cancelation 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

ending ~

Go context 介绍和使用的更多相关文章

  1. Golang的Context介绍及其源码分析

    简介 在Go服务中,对于每个请求,都会起一个协程去处理.在处理协程中,也会起很多协程去访问资源,比如数据库,比如RPC,这些协程还需要访问请求维度的一些信息比如说请求方的身份,授权信息等等.当一个请求 ...

  2. Tomcat下server.xml中context介绍

    conf/Context.xml是Tomcat公用的环境配置;若在server.xml中增加<Context path="/test" docBase="D:\te ...

  3. Android Context介绍

    转载(Android Context完全解析与各种获取Context方法):https://www.cnblogs.com/chenxibobo/p/6136693.html

  4. 理解Go Context机制

    1 什么是Context 最近在公司分析gRPC源码,proto文件生成的代码,接口函数第一个参数统一是ctx context.Context接口,公司不少同事都不了解这样设计的出发点是什么,其实我也 ...

  5. Android上下文Context

    Android上下文Context介绍 在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中时刻的在与它打交道,例如:Service.BroadcastReceiv ...

  6. Golang 高效实践之并发实践context篇

    前言 在上篇Golang高效实践之并发实践channel篇中我给大家介绍了Golang并发模型,详细的介绍了channel的用法,和用select管理channel.比如说我们可以用channel来控 ...

  7. Go实现海量日志收集系统(三)

    再次整理了一下这个日志收集系统的框,如下图 这次要实现的代码的整体逻辑为: 完整代码地址为: https://github.com/pythonsite/logagent etcd介绍 高可用的分布式 ...

  8. Flask类的属性和方法大全

    Flask Property__class____dict____doc____module__app_ctx_globals_classconfig_classdebugdefault_config ...

  9. OpenGL Windows 窗口程序环境搭建

    OpenGL环境搭建步骤: Downloading OpenGL 根据官网的说法: In all three major desktop platforms (Linux, macOS, and Wi ...

随机推荐

  1. docker 安装redis 并配置外网可以访问

    1, docker 拉去最新版本的redis docker pull redis #后面可以带上tag号, 默认拉取最新版本 2, docker安装redis container 安装之前去定义我们的 ...

  2. darknet 的python接口使用

    首先,python接口文件在安装好的darknet目录下的python文件夹,打开就可以看到 这里的darknet.py文件就是python接口 用编辑器打开查看最后部分代码: 使用十分简单,先将网络 ...

  3. [转]EL表达式判断是否为空,判断是否为空字符串

    原文地址:https://blog.csdn.net/zhaofuqiangmycomm/article/details/79442730 El表达式判断是否为空字符串 ${empty 值}  返回t ...

  4. IDEA优化配置,提高启动和运行速度

    IDEA优化配置,提高启动和运行速度   参考链接:https://blog.csdn.net/riju4713/article/details/83217013,http://www.pc0359. ...

  5. 安装ORACLE服务出现Oracle Net Configuration Assistant 失败问题【我】

    安装ORACLE服务出现Oracle Net Configuration Assistant 失败问题 本地安装oracle11g,报错提示: 参考下面文章: 报错原因: 主要是对文件系统的访问权限问 ...

  6. 零基础学Python-第一章 :Python介绍和安装-03.Python的安装

    官方版本的python下载以及安装方法,以及pycharm的安装和打开. 社区版就可以完全支持我们的需求了. 点击左侧的图片到右边. 在命令行输入python3 exit() 退出命令行的编辑器. p ...

  7. React错误收集

    1.  Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/ ...

  8. WITH ROLLUP、WITH CUBE、GROUPING语句的应用

    作者:Bobby0322 CUBE 和 ROLLUP 之间的区别在于:CUBE 运算符生成的结果集是多维数据集.多维数据集是事实数据的扩展,事实数据即记录个别事件的数据.扩展建立在用户打算分析的列上. ...

  9. jenkins-不能启动

    FROM centos RUN docker run -tdi --privileged centos init ADD jdk-8u171-linux-x64.tar.gz /usr/local A ...

  10. 【转】行内元素和inline-block产生的水平空隙bug

    重构工程师们在设计代码时,有喜欢手动删除行内元素之间产生的额外空隙,并通过设置margin或padding来获取想要间距吗?如代码: <div class=“”><span clas ...