背景

  最近项目需要在实现一个视频加工的功能主要是用的ffmPEg命令行工具后面会出文章讲一讲,这里面有用到协程,部门老大review代码后把我屌 了😢,问我怎么没对协程设置超时时间。我当时是用的WaitGroup包,去等待协程结果的,这样会有一个问题就是如果协程处理时间太长就会出现协程堆积的情况爆cup、爆内存,这个问题在我们目前的生产环境是存在的并且有点严重,因为一直都有开发任务所以一直没去处理。

一、基本原理

<-chan struct{}

二、使用Done方法阻塞协程,等待执行结果

package main

import (
	"context"
	"testing"
	"time"
)

func TestContext(t *testing.T)  {
	//context.WIThTimeout 需要传入一个上下文父上下文,这里只有一个协程所以用context.Background()声明一个上下文即可
	ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*2) //定义一个带有超时时间的上下文
	go func() {
		defer cancelFunc()  //执行完毕后就手动取消上下文,避免傻傻的等待超时,浪费时间
		time.Sleep(time.Second * 5) //默认耗时操作
	}()
	<-ctx.Done() //等待协程执行完成

	
	//判断执行结果,ctx.Err(),可以拿到执行错误,可以判断是否有超时
	//err := ctx.Err()
	//if err!=nil {
	//	if err.Error() == "context canceled" {
	//		fmt.PRintln("协程执行完毕")
	//	}
	//	if err.Error() == "context deadline exceeded" {
	//		fmt.Println("上下文超时")
	//	}
	//}

}
=== RUN   TestContext
--- PASS: TestContext (2.00s)
PASS

1、说明

context.WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
parenttimeoutContextCancelFunc

2、Err() error

CancelFunccontext canceled
context deadline exceeded
CancelFunc

  4、源码备注

// If Done is not yet closed, Err returns nil.
// If Done is closed, Err returns a non-nil error explaining why:
// Canceled if the context was canceled
// or DeadlineExceeded if the context's deadline passed.
// After Err returns a non-nil error, successive calls to Err return the same error.
Err() error

3、Done() <-chan struct{}

CancelFunc

三、context+select 形式

package main

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

func TestContext(t *testing.T)  {
	//context.WithTimeout 需要传入一个上下文父上下文,这里只有一个协程所以用context.Background()声明一个上下文即可
	ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*2) //定义一个带有超时时间的上下文
	go func() {
		defer cancelFunc() //执行完毕后就手动取消上下文,避免傻傻的等待超时,浪费时间
		time.Sleep(time.Second * 1)  //模拟耗时操作
	}()
	for  {
		select {
		case <-ctx.Done():
			fmt.Println("协程序执行完了")
			fmt.Println(ctx.Err())
			return
		default:  //去掉default的话,select就会阻塞主协程,导致后面的代码无法执行

		}
		fmt.Println("协程还没执行完!")
		time.Sleep(time.Millisecond*500) //只是为了让输出少点
	}
}
=== RUN   TestContext
协程还没执行完!
协程还没执行完!
协程序执行完了
context canceled
--- PASS: TestContext (1.01s)
PASS

脚本宝典总结

以上是脚本宝典为你收集整理的golang使用context控制协程超时时间全部内容,希望文章能够帮你解决golang使用context控制协程超时时间所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。