Context是由Golang官方开发的并发控制包,一方面可以用于当请求超时或者取消时候,相关的goroutine马上退出释放资源,
另一方面Context本身含义就是上下文,其可以在多个goroutine或者多个处理函数之间传递共享的信息。
创建一个新的context,必须基于一个父context,新的context又可以作为其他context的父context。
所有context在一起构造成一个context树。
package main
import (
"context"
"fmt"
"math/rand"
"runtime"
"time"
)
func main(){
//ctx 超时控制
ctx,cancel:=context.WithTimeout(context.Background(),3*time.Second)
defer cancel()
go SlowOperation(ctx)
go func() {
for {
time.Sleep(300*time.Microsecond)
fmt.Println("goroutine:",runtime.NumGoroutine())
}
}()
time.Sleep(4*time.Second)
}
func SlowOperation(ctx context.Context){
done:=make(chan int,1)
go func() {
dur:=time.Duration(rand.Intn(5)+1)*time.Second
time.Sleep(dur)
done <- 1
}()
select {
case <-ctx.Done():
fmt.Println("slowOperation timeout:",ctx.Err())
case <-done:
fmt.Println("complete work")
}
}
上面代码会不停打印当前groutine数量,可以观察到SlowOperation函数执行超时之后,goroutine数量由4个变成2个,相关goroutetine退出了
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
Context接口一共包含四个方法:
- Deadline:返回绑定该context任务的执行超时时间,若未设置,则ok等于false
- Done:返回一个只读通道,当绑定该context的任务执行完成并调用cancel方法或者任务执行超时时候,该通道会被关闭
- Err:返回一个错误,如果Done返回的通道未关闭则返回nil,如果context如果被取消,返回
Canceled
错误,如果超时则会返回DeadlineExceeded
错误 - Value:根据key返回,存储在context中k-v数据