更新时间:

#golang context

#什么是context?

   context是一种通知手段,例如现在后台有一个监听进程,你要如何在主进程中停止这个监听进程呢?有人会说,select+channel好了嘛,只要主进程往channel里面写数据,后台监听进程读取到channel里面的数据就停止,这其实是一个不错的方法,但是如果后台进程又起了100个后台进程呢?我关闭后台进程的时候,想顺便把后台进程起的子进程一起关掉,select+channel明显就不太行了。

   子进程会起子进程,我们很容易就能联想到树,监听进程就是这棵树的根结点,监听进程起的子进程相当于这颗树的某个节点或者叶子节点,其实面对这种场景,我门想要的就是,如果我们向这棵树的某个节点程序发送通知,那么该节点的子节点程序也能收到该通知,而context就是定义这种树形关系的工具,context与context是有父子关系的,只要往ctx1发送消息,那么ctx1的子ctx2就能接收到消息,但是我们并不能决定context发送消息的内容,只能发送取消通知,就像我拍拍你的头,跟你说乖,一样简单的问候。


type Context interface {
	
	Deadline() (deadline time.Time, ok bool) // Deadline方法指示一段时间后当前goroutine是否会被取消
 
	Done() <-chan struct{}
	
	Err() error  // Err 方法在 channel 关闭之前读取没有意义,会直接返回 nil,只有在关闭之后解释goroutine被取消的原因。
	
	Value(key interface{}) interface{}

   Dealine():context是有定时功能,到了设定时间,就会自动发送消息,这个方法就是返回所设定的时间,有没有设定定时。

   Done():一个只读的channel,如果context收到通知,这个channel就会有数据

   Err():返回取消的错误原因,因为什么Context被取消

   Value():context还能存key:value,不过key和value都应该为线程安全的类型

### 例子
package main
 
import (
	"context"
	"fmt"
	"time"
)
 
func main() {
	parentContext := context.TODO()
	cc,c :=  context.WithCancel(parentContext)
	go say(cc,"a")
	go say(cc,"b")
	time.Sleep(10*time.Second)
	c() // canDeleteFunc--
	time.Sleep(10*time.Second)
 
}
 
func say(ctx context.Context, name string){
	for {
		select {
		case <-ctx.Done():
			fmt.Println("goodBy:", ctx.Err())
			return
		default:
			fmt.Println("hello I am:", name)
			time.Sleep(2 * time.Second)
		}
	}
}

context.TODO()相当于定义了一个父的context,就是这棵树的根结点

   WithCancel(parentContext)相当于给这个parentContext定义了一个子节点,这个函数会返回2个参数,子context和发送消息的函数canDeleteFunc,只要我们调用canDeleteFunc,那么该context和它的子context就能通过Done接收到该消息,除了WithCancel之外,还有好几个With开头的函数都能够定义子Context,他们一一对应Context接口的几个函数,有兴趣可以自己了解一下。

#总结:

  1.Context是一种通知手段   2.Context通过TODO/Background定义父节点,通过With系列函数定义子Context   3.Context通过设定时间/运行某个函数发送通知消息,通过Done函数接收消息   4.只要给某个Context发送消息,那么该Context及其子Context就能够接收到消息

https://blog.csdn.net/fbher/article/details/114274255


#评论

#评论 1 · 2023-02-23T06:31:13.785000Z

它使得一个request范围内所有goroutine运行时的取消可以得到有效的控制。当最上层的 goroutine 因为某些原因执行失败时,下层的 Goroutine 由于没有接收到这个信号所以会继续工作;但是当我们正确地使用 context.Context 时,就可以在下层及时停掉无用的工作以减少额外资源的消耗。