golang的context的理解
文章美化版
context介绍
在Go服务器中,每个传入请求都在其自己的goroutine中进行处理。 请求处理程序通常会启动其他goroutine来访问后端,例如数据库和RPC服务。 处理请求的goroutine集合通常需要访问特定于请求的值,例如最终用户的身份,授权令牌和请求的期限。 当一个请求被取消或超时时,处理该请求的所有goroutine应该迅速退出,以便系统可以回收他们正在使用的任何资源。
GO的官方就开发了 context
包,可以轻松地跨API边界将请求范围的值,取消信号和截止日期传递给处理请求的所有goroutine。 该软件包可作为上下文公开使用。
context的解决问题的场景
场景一
使用conext来解决一下,当请求结束后,立马停止正在做的事情
func main() {
http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
log.Println("我接收到了请求")
var wg sync.WaitGroup
wg.Add(1)
// 做 A 事情
go func() {
defer wg.Done()
select {
case <-request.Context().Done(): // 用来判断 这次请求是是否结束了
// do something
log.Println("我 很快乐的结束了")
}
}()
// 做B事情
// 做C事情
wg.Wait()
})
fmt.Println(http.ListenAndServe(":8080", nil))
}
使用context 用来解决 goroutine 之间退出通知、元数据传递的功能(同步请求特定数据、取消信号以及处理请求的截止日期)
context的怎么使用
使用context来 通知子协成
// 使用context来 通知子协成结束
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
// 500ms
go handle3(ctx, 3*time.Second)
// 如果 select中的 任何一个case都没有满足的 则会指定等待下去直到有符合条件的case
select {
case <-ctx.Done():
// main context deadline exceeded 代表 是由于超过了过期 时间的导致的错误
fmt.Println("main", ctx.Err())
}
// 避免程序,过早退出导致 子协成的 没有打印出来
time.Sleep(time.Second * 1)
}
// 使用context 同步信号
func handle3(ctx context.Context, duration time.Duration) {
select {
case <-ctx.Done():
fmt.Println("handle", ctx.Err())
case <-time.After(duration):
fmt.Println("process request with", duration)
}
}
使用context 来向 子协成传递数据(key一定是可以比较的)
func main()