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. Python3.6 提示 ModuleNotFoundError: No module named '_ssl' 模块问题

    国内 163 yum 源挺好用 (中科大的也不错) http://mirrors.163.com/.help/CentOS6-Base-163.repo yum install openssl-dev ...

  2. java中String常量的存储原理

    相关题目(运行结果在代码注释后面) 1. package StringTest; public class test1 { public static void main(String[] args) ...

  3. java中 16进制字符串 与普通字符串 与 byte数组 之间的转化

    方法依赖commons-codec包  maven的引入方式如下 <dependency> <groupId>commons-codec</groupId> < ...

  4. Django系统

    #Django系统 -环境 - python3.6 - django1.8 -参考资料 - [django中文教程](http://python.usyiyi.cn) - django架站的16堂课 ...

  5. 创建存储过程 in,out,inout

    in: 输入参数,存储过程如果修改了参数值,那么不能被返回. out:输出参数,存储过程中修改了参数值,可以被返回.inout:输入参数,存储过程如果修改了参数值,可以被返回 注意参数格式:  in  ...

  6. 再一波Python实战项目列表

    前言: 近几年Python可谓是大热啊,很多人都纷纷投入Python的学习中,以前我们实验楼总结过多篇Python实战项目列表,不但有用还有趣,最主要的是咱们实验楼不但有详细的开发教程,更有在线开发环 ...

  7. 面试 Java 高级后端开发,要准备哪些知识点?

    其实公司肯花时间让你去面试,前提条件一定是通过你的简历,一定发现了你和公司的匹配点,也就是说,一定是有录用意向的. 在技术面试的时间段里(最长1个小时),你如果能展现你的优势那是最好的,但如果你做不到 ...

  8. python的高级数组之稀疏矩阵

    稀疏矩阵的定义: 具有少量非零项的矩阵(在矩阵中,若数值0的元素数目远多于非0元素的数目,并且非0元素分布没有规律时,)则称该矩阵为稀疏矩阵:相反,为稠密矩阵.非零元素的总数比上矩阵所有元素的总数为矩 ...

  9. User root is not allowed to impersonate anonymous

    User root is not allowed to impersonate anonymous ava.lang.RuntimeException: org.apache.hadoop.ipc.R ...

  10. windows 中的类似于sudo的命令(在cmd中以另一个用户的身份运行命令)

    linux中我们习惯用sudo命令来临时用另一个用户的身份执行命令. windows中,通常我们需要用管理员权限执行命令的时候通常是 右键->run as administrator. 用着键盘 ...