1.定义
WithTimeout用来创建超时就会取消的context,内部实现就是WithDealine,传递给WithDealine的过期时间就是当前时间加上timeout时间
2.内部实现
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
2.1 解释
parent : 类型实际就是一个context,那么既然定义为”parent“,实际上是使用者传入的是一个父类的上下文。
timeout:顾名思义,超时时间
出参有2个,一个是context,其实是根据父类context,生成一个子类的context,且返回一个取消函数。
换言之:
context包的WithTimeout()函数接受一个 Context 和超时时间作为参数,返回其子Context和取消函数cancel
新创建协程中传入子Context做参数,且需监控子Context的Done通道,若收到消息,则退出
需要新协程结束时,在外面调用 cancel 函数,即会往子Context的Done通道发送消息
若不调用cancel函数,到了原先创建Contetx时的超时时间,它也会自动调用cancel()函数,即会往子Context的Done通道发送消息
3.使用
比如我想异步调用一个功能,但是我最多只能等待1s,如果没返回结果,我就不等了。多适用于并发rpc请求不同接口,想在规定时间内拿到尽可能多的结果。
3.1实例1 规定时间内显示调用cancel函数
func TestCtxWithCancel(t *testing.T) {
ctx := context.Background()
ctx1, cancel := context.WithTimeout(ctx, 1*time.Second)
//ctx1, _ := context.WithTimeout(ctx, 1*time.Second)
fmt.Print("当前时间:")
fmt.Println(time.Now().Unix())
go slowS(ctx1)
time.Sleep(1 * time.Second)
fmt.Print("1s后的时间:")
fmt.Println(time.Now().Unix())
cancel()
fmt.Println("end")
}
func slowS(ctx context.Context) {
time.Sleep(3 * time.Second)
fmt.Println("我已经等待3秒了")
}
输出:
3.2实例,由context自动超时取消
func TestCtxWithCancel(t *testing.T) {
ctx := context.Background()
//ctx1, cancel := context.WithTimeout(ctx, 1*time.Second)
ctx1, _ := context.WithTimeout(ctx, 1*time.Second)
fmt.Print("当前时间:")
fmt.Println(time.Now().Unix())
go slowS(ctx1)
time.Sleep(1 * time.Second)
fmt.Print("1s后的时间:")
fmt.Println(time.Now().Unix())
//cancel()
fmt.Println("end")
}
func slowS(ctx context.Context) {
time.Sleep(3 * time.Second)
fmt.Println("我已经等待3秒了")
}
输出: