context.WithTimeout
看着简单,复杂环境下用着难
普通示例1
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(5))
defer cancel()
fmt.Println("main=>", time.Now())
go worker()
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now()) // worker()超过了5s,但是依旧5s后退出
}
func worker() {
fmt.Println("worker=>", time.Now())
i := 0
for {
i++
if i > 100000000 {
fmt.Println("worker run", time.Now())
i = 0
}
}
fmt.Println("worker<=", time.Now())
}
普通示例2
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(5))
defer cancel()
fmt.Println("main=>", time.Now())
go worker()
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now()) // worker()没有超过5s,但是依旧5s后退出
}
func worker() {
fmt.Println("worker=>", time.Now())
i := 0
for {
i++
if i > 100 {
break
}
}
fmt.Println("worker<=", time.Now())
}
普通示例3
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(5))
defer cancel()
fmt.Println("main=>", time.Now())
go worker()
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now()) // worker() sleep 10秒,但是依旧5s后退出
}
func worker() {
fmt.Println("worker=>", time.Now())
time.Sleep(time.Second * time.Duration(10))
fmt.Println("worker<=", time.Now())
}
普通示例4
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(5))
defer cancel()
fmt.Println("main=>", time.Now())
go worker()
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now()) // worker() sleep 2秒,但是依旧5s后退出
}
func worker() {
fmt.Println("worker=>", time.Now())
time.Sleep(time.Second * time.Duration(2))
fmt.Println("worker<=", time.Now()) // worker() sleep 2秒,但是依旧5s后退出
}
奇怪示例1
Test_CancelTime函数5秒退出
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(5))
defer cancel()
fmt.Println("main=>", time.Now())
go worker(ctx, 100)
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now())
}
func worker(ctx context.Context, n int) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(10))
defer cancel()
fmt.Println("worker=>", time.Now())
go workInner(ctx, n)
for range ctx.Done() {
fmt.Println("worker receive notice", time.Now())
break
}
fmt.Println("worker<=", time.Now())
}
func workInner(ctx context.Context, n int) {
group, newCtx := errgroup.WithContext(ctx)
group.SetLimit(3)
for i := 0; i < n; i++ {
curIndex := i
group.Go(func() (err error) {
defer func() {
if e := recover(); e != nil {
logs.CtxError(newCtx, "[workerInner] panic recovered: %v", string(debug.Stack()))
}
}()
fmt.Printf("workerInner %v=>%v\n", curIndex, time.Now())
time.Sleep(time.Second * time.Duration(2))
fmt.Printf("workerInner %v<=%v\n", curIndex, time.Now())
return nil
})
}
if err := group.Wait(); err != nil {
logs.CtxError(newCtx, "[workerInner] group failed, err=%v", err)
return
}
}
奇怪示例2
Test_CancelTime函数依旧是5秒退出
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(5))
defer cancel()
fmt.Println("main=>", time.Now())
go worker(ctx, 100)
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now())
}
func worker(ctx context.Context, n int) {
ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(10))
defer cancel()
fmt.Println("worker=>", time.Now())
go workInner(ctx, n)
for range ctx.Done() {
fmt.Println("worker receive notice", time.Now())
break
}
fmt.Println("worker<=", time.Now())
}
func workInner(ctx context.Context, n int) {
group, newCtx := errgroup.WithContext(ctx)
group.SetLimit(3)
for i := 0; i < n; i++ {
curIndex := i
group.Go(func() (err error) {
defer func() {
if e := recover(); e != nil {
logs.CtxError(newCtx, "[workerInner] panic recovered: %v", string(debug.Stack()))
}
}()
fmt.Printf("workerInner %v=>%v\n", curIndex, time.Now())
time.Sleep(time.Second * time.Duration(2))
fmt.Printf("workerInner %v<=%v\n", curIndex, time.Now())
return nil
})
}
if err := group.Wait(); err != nil {
logs.CtxError(newCtx, "[workerInner] group failed, err=%v", err)
return
}
}
奇怪示例3
func Test_CancelTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(10))
defer cancel()
fmt.Println("main=>", time.Now())
go worker(ctx, 100)
for range ctx.Done() {
fmt.Println("main receive notice", time.Now())
break
}
fmt.Println("main<=", time.Now())
}
func worker(ctx context.Context, n int) {
ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(4))
defer cancel()
fmt.Println("worker=>", time.Now())
go workInner(ctx, n)
for range ctx.Done() {
fmt.Println("worker receive notice", time.Now())
break
}
fmt.Println("worker<=", time.Now())
}
func workInner(ctx context.Context, n int) {
group, newCtx := errgroup.WithContext(ctx)
group.SetLimit(3)
for i := 0; i < n; i++ {
curIndex := i
group.Go(func() (err error) {
defer func() {
if e := recover(); e != nil {
logs.CtxError(newCtx, "[workerInner] panic recovered: %v", string(debug.Stack()))
}
}()
fmt.Printf("workerInner %v=>%v\n", curIndex, time.Now())
time.Sleep(time.Second * time.Duration(2))
fmt.Printf("workerInner %v<=%v\n", curIndex, time.Now())
return nil
})
}
if err := group.Wait(); err != nil {
logs.CtxError(newCtx, "[workerInner] group failed, err=%v", err)
return
}
}
返回值
main=> 2023-07-05 20:48:34.792095 +0800 CST m=+2.173696454
worker=> 2023-07-05 20:48:34.792172 +0800 CST m=+2.173773493
workerInner 2=>2023-07-05 20:48:34.792234 +0800 CST m=+2.173835427
workerInner 1=>2023-07-05 20:48:34.792265 +0800 CST m=+2.173866728
workerInner 0=>2023-07-05 20:48:34.792269 +0800 CST m=+2.173870488
workerInner 1<=2023-07-05 20:48:36.792364 +0800 CST m=+4.173964493
workerInner 0<=2023-07-05 20:48:36.792383 +0800 CST m=+4.174001401
workerInner 3=>2023-07-05 20:48:36.792411 +0800 CST m=+4.174011412
workerInner 2<=2023-07-05 20:48:36.792446 +0800 CST m=+4.174046582
workerInner 4=>2023-07-05 20:48:36.792444 +0800 CST m=+4.174044861
workerInner 5=>