1. 概述

  go语言中goroutine之间的关联关系,缺乏维护,在erlang中有专门的机制来保障新开协程的生命周期,在go语言中,只能通过channel + select来实现,但不够直观,很绕。
  Context 通常被译作 上下文 ,它是一个比较抽象的概念,一般理解为程序单元的一个运行状态、现场、快照。上下上下则是存在上下层的传递, 上 会把内容传递给 下 。
  在Go语言中,程序单元也就指的是Goroutine。context 包不仅实现了在程序单元之间共享状态变量的方法,同时能通过简单的方法,使我们在被调用程序单元的外部,通过设置ctx变量值,将过期撤销信号传递给被调用的程序单元。

  在go服务器中(http服务器),对于每个请求的request都是在单独的goroutine中进行的,处理一个request也可能涉及多个goroutine之间的交互, 使用context可以使开发者方便地在这些goroutine里传递request相关的数据、取消goroutine的signal或截止时间

  Done 方法在Context被取消或超时时返回一个close的channel,close的channel可以作为广播通知,告诉给context相关的函数要停止当前工作然后返回。

  当一个父operation启动一个goroutine用于子operation,这些子operation不能够取消父operation。下面描述的WithCancel函数提供一种方式可以取消新创建的Context.

  Context可以安全的被多个goroutine使用。开发者可以把一个Context传递给任意多个goroutine然后cancel这个context的时候就能够通知到所有的goroutine。

Err方法返回context为什么被取消。

Deadline返回context何时会超时。

Value返回context相关的数据。

需要注意的就是 调用CancelFunc会取消child以及child生成的context,取出父context对这个child的引用,停止相关的计数器

实战:

  1. context.Background 只应用在最高等级,作为所有派生 context 的根。
  2. context.TODO 应用在不确定要使用什么的地方,或者当前函数以后会更新以便使用 context。
  3. context 取消是建议性的,这些函数可能需要一些时间来清理和退出。
  4. context.Value 应该很少使用,它不应该被用来传递可选参数。这使得 API 隐式的并且可以引起错误。取而代之的是,这些值应该作为参数传递。
  5. 不要将 context 存储在结构中,要在函数中显式传递它们,最好是作为第一个参数。
  6. 永远不要传递不存在的 context 。相反,如果您不确定使用什么,使用一个 ToDo context。
  7. Context 结构没有取消方法,因为只有派生 context 的函数才可以取消 context。

参考示例1:

package main

import (
"context"
"log"
"os"
"time"
) var logg *log.Logger func someHandler() {
ctx, cancel := context.WithCancel(context.Background())
go doStuff(ctx) //10秒后取消doStuff
time.Sleep(10 * time.Second)
cancel() } //每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
for {
time.Sleep(1 * time.Second)
select {
case <-ctx.Done():
logg.Printf("done")
return
default:
logg.Printf("work")
}
}
} func main() {
logg = log.New(os.Stdout, "", log.Ltime)
someHandler()
logg.Printf("down")
time.Sleep(10 * time.Second)
}

  输出

18:00:17 work
18:00:18 work
18:00:19 work
18:00:20 work
18:00:21 work
18:00:22 work
18:00:23 work
18:00:24 work
18:00:25 work
18:00:26 down
18:00:26 done

  参考示例2:

package main

import (
"context"
"log"
"os"
"time"
) var logg *log.Logger func doTimeOutStuff(ctx context.Context) {
for {
time.Sleep(1 * time.Second) if deadline, ok := ctx.Deadline(); ok { //设置了deadl
logg.Printf("deadline set")
if time.Now().After(deadline) {
logg.Printf(ctx.Err().Error())
return
} } select {
case <-ctx.Done():
logg.Printf("done")
return
default:
logg.Printf("work")
}
}
} func timeoutHandler() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
go doTimeOutStuff(ctx)
// go doStuff(ctx) time.Sleep(10 * time.Second) cancel() } func main() {
logg = log.New(os.Stdout, "", log.Ltime)
timeoutHandler()
logg.Printf("down")
time.Sleep(10 * time.Second)
}

  输出:

18:04:37 deadline set
18:04:37 work
18:04:38 deadline set
18:04:38 work
18:04:39 deadline set
18:04:39 work
18:04:40 deadline set
18:04:40 work
18:04:41 deadline set
18:04:41 context deadline exceeded
18:04:46 down

  参考链接:

https://studygolang.com/articles/12566

https://www.cnblogs.com/zhangboyu/p/7456606.html

https://studygolang.com/articles/13866?fr=sidebar

context使用的更多相关文章

  1. Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

    执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...

  2. spring源码分析之<context:property-placeholder/>和<property-override/>

    在一个spring xml配置文件中,NamespaceHandler是DefaultBeanDefinitionDocumentReader用来处理自定义命名空间的基础接口.其层次结构如下: < ...

  3. spring源码分析之context

    重点类: 1.ApplicationContext是核心接口,它为一个应用提供了环境配置.当应用在运行时ApplicationContext是只读的,但你可以在该接口的实现中来支持reload功能. ...

  4. CSS——关于z-index及层叠上下文(stacking context)

    以下内容根据CSS规范翻译. z-index 'z-index'Value: auto | <integer> | inheritInitial: autoApplies to: posi ...

  5. Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误——SHH框架

    SHH框架工程,Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误 1.查看配置文件web.xml中是否配置.or ...

  6. mono for android Listview 里面按钮 view Button click 注册方法 并且传值给其他Activity 主要是context

    需求:为Listview的Item里面的按钮Button添加一个事件,单击按钮时通过事件传值并跳转到新的页面. 环境:mono 效果: 布局代码 主布局 <?xml version=" ...

  7. Javascript的“上下文”(context)

    一:JavaScript中的“上下文“指的是什么 百科中这样定义: 上下文是从英文context翻译过来,指的是一种环境. 在软件工程中,上下文是一种属性的有序序列,它们为驻留在环境内的对象定义环境. ...

  8. spring源码分析之<context:component-scan/>vs<annotation-config/>

    1.<context:annotation-config/> xsd中说明: <xsd:element name="annotation-config"> ...

  9. 【Android】 context.getSystemService()浅析

    同事在进行code review的时候问到我context中的getSystemService方法在哪实现的,他看到了一个ClipBoardManager来进行剪切板存储数据的工具方法中用到了cont ...

  10. context:component-scan" 的前缀 "context" 未绑定。

    SpElUtilTest.testSpELLiteralExpressiontestSpELLiteralExpression(cn.zr.spring.spel.SpElUtilTest)org.s ...

随机推荐

  1. HDU 6311 Cover (无向图最小路径覆盖)

    HDU 6311 Cover (无向图最小路径覆盖) Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...

  2. Python 模块定义、导入、优化详解

    一.定义 模块:用来从逻辑上组织 python 代码(变量,函数,类, 逻辑:实现一个功能),本质就是 .py 结尾的 python文件(例如:test.py文件,对应的模块名:test) 包:用来从 ...

  3. Lombok 介绍

    Lombok使用 介绍 在项目中使用Lombok可以减少很多重复代码的书写.比如说getter/setter/toString等方法的编写. IDEA中的安装 打开IDEA的Setting –> ...

  4. JavaScript中innerHTML与innerText,createTextNode的区别

    innerHTML和innerText 它们都会把元素内内容替换掉,区别在于: innerHTML 会把替换内容里的 HTML 标记解释执行. innerText 会把替换内容里的 HTML 标记原样 ...

  5. Android的ViewPager的学习

    这篇博客是对慕课网上看到的视频里学习到的知识的一些记录,让自己能够加深理解.视频地址:http://www.imooc.com/learn/1116 在这个视频中,目标是实现类似微信的主界面之间的切换 ...

  6. 学号 20175201张驰 《Java程序设计》第7周学习总结

    学号 20175201张驰 <Java程序设计>第7周学习总结 教材学习内容总结 第八章 String类能有效地处理字符序列信息,它的常用方法有: public int length()可 ...

  7. Servlet学习1

    1.首先在Tomcat的webapp目录下新建文件夹myWebapp,作为自己的web应用. 2.myWebapp下新建WEB-INF(必须这个名)目录,WEB-INF下新建classes目录放置se ...

  8. vi命令撤销及恢复

    u   :插销上一步操作 Ctrl + r :恢复被撤销的上一步操作

  9. Ribbon标题语句

    感谢每一次成长的喜悦和感动,谢谢一路有你!我会比从前更爱你,希望     你能陪我走过这一生!网址:http://www.uc123.com/

  10. redis----------基本命令使用

    1.查看全部缓存数据的key keys * 2.清空当前redis数据库缓存 flushdb  (redis默认由16个库(0~15号). 且默认使用的是0号库.库之间的切换使用select命令例如: ...