golang中的ctx deadline cancel到底如何使用

这个问题其实迷惑了我很久时间,今天写一下。

1. 见https://blog.csdn.net/qq_17612199/article/details/89786256,博文。

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ctx, cancel := context.WithTimeout(context.TODO(), time.Second*3)
    defer cancel() 
    go task(ctx)
    time.Sleep(time.Second * 10)
}

func task(ctx context.Context) {
    ch := make(chan struct{}, 0)
    go func() {
        // 模拟4秒耗时任务
        time.Sleep(time.Second * 4)
        ch <- struct{}{}
    }()
    select {
    case <-ch:
        fmt.Println("done")
    case <-ctx.Done():
        fmt.Println("timeout")
    }
}

本质上对代码的超时判断必须独立于主干逻辑代码的执行,由当前线程判断是超时还是业务逻辑做完。开启子线程执行业务逻辑。在子线程中如果进行超时判断,同样需要在子线程中进行示例代码的编写。

在增加一个我自己写的测试用例:

func main() { //这个 { 不能另起一行
	ctx, _ := context.WithTimeout(context.TODO(), 2*time.Second)
	go func(ctx context.Context) {
		fmt.Printf("begin func1\n")
		go func(ctx context.Context) {
			ch := make(chan error, 0)
			go func(ctx context.Context) {
				fmt.Printf("begin func2\n")
				time.Sleep(5 * time.Second)
				if ctx.Err() != nil {
					dealLine, dead := ctx.Deadline()
					fmt.Printf("do not call end func2,deadLine:%v,dead:%v\n", dealLine, dead)
					return
				}
				fmt.Printf("end func2\n")
				ch <- nil
			}(ctx)
			select {
			case <-ch:
				fmt.Printf("ok")
			case <-ctx.Done():
				fmt.Printf("err:%v\n", ctx.Err())
			}
		}(ctx)
		fmt.Printf("end func1\n")
	}(ctx)
	time.Sleep(10 * time.Second)
}

2. 比照java中netty框架的实现,超时的实现是采用时间轮操作。req发出后不管.收到rsp请求后,就从时间轮中删除该req。如果时间轮到期,则说明该req超时,需要进行超时处理(好像是这么实现的,时间久了,不记得了)

也就是超时时间的判断没有其他更好的方法,必须独立于主干业务逻辑中执行。

3. context中还有个方法,ctx.Err().如果超时了或者canel方法被调用了,则ctx.Err()是能返回对应的error错误的。因此有时候我们看到的错误提示,timeout exceed 什么的就是ctx.Err()返回的error错误。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值