Go context的理解

163 阅读2分钟

context是什么

context是一个Go语言独有的结构,不太好用其他语言的类型做例子,具体的功能需要通过例子来表示

channel和select

在了解context使用方法时,需要先理解channel和select的使用,在这里我不详细解释,大概介绍下他们的作用

channel

channel类似于java里的阻塞队列,是一个优雅的线程安全的工具

想了解他的原理,可以看下我之前发的详解channel

juejin.cn/post/697140…

select

select也是go独有的一个东西,他的使用方法类似于switch,但他的输入值只能是channel,如果没有channel可以操作就会被阻塞,有的话就会选择case运行。如果有多个channel可以操作,就随机选择一个运行。如果有default方法的话,即时没有channel可以操作,也不会阻塞,而是直接调用default的方法。

示例

首先协程在运行过程中,它指令没有执行完是不会终止的。也就是说写了一个死循环,协程自己会一直运行下去。那么想要终止协程的话,有三种方法

  1. 使用全局变量
  2. 使用select,channel
  3. 使用context

全局变量是最容易想到的方法,这种方法的问题就是会有线程安全问题,所以需要使用锁。

使用select,channel

func recycle(c <-chan int) {
	for true {
		select {
		case <-c:
			fmt.Println("a")
		default:
			fmt.Println("循环中")
		}
	}

}

相对于全局变量更优雅,对于协程较少来说,是可以使用的。但是协程如果嵌套协程或者有很多层协程,这个关系会很复杂。

所以最优雅的方式就是使用context,这也就引出了他的一个功能,他可以进行信号传递,可以实现上游取消信号,下游任务自行取消的效果

功能

  1. 传递key value
  2. 超时控制
  3. 主动取消控制

context是一个树形结构,当控制一个节点的时候,意味着他的子节点也会被控制。

例如有一个服务调用超时,应该返回失败的数据,但是子协程还在运行,这是没有必要的,就可以通过context阻止子协程的运行。

使用方法

形象的来说就是把 Context 想象为一条河流流过你的程序,每个方法参数开头都一定要是context