GoLang

Go Context之WithTimeout的含义与使用

2024-06-25  本文已影响0人  丿灬尘埃

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,且返回一个取消函数。
换言之:

  1. context包的WithTimeout()函数接受一个 Context 和超时时间作为参数,返回其子Context和取消函数cancel

  2. 新创建协程中传入子Context做参数,且需监控子Context的Done通道,若收到消息,则退出

  3. 需要新协程结束时,在外面调用 cancel 函数,即会往子Context的Done通道发送消息

  4. 若不调用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秒了")
}

输出:


image.png

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秒了")
}

输出:


image.png
上一篇 下一篇

猜你喜欢

热点阅读