admin 发表于 2022-1-21 00:17:20

golang:使用context控制协程goroutine运行超时时间

■实例说明
我们很容易启动一个goroutine协程执行指定任务,但如果不控制协程的执行超时时间,很容易造成程序实行超时。
1)通过context控制协程超时时间
2)协程正确返回数据的方式
3)协程错误返回数据的方式,当然有时候这不是一种错误,而是特性。详见代码注释

■实例代码
package main

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

// DoJob 一个最多执行timeout时间的方法
func DoJob(timeout time.Duration) {
      // 定义一个包含超时时间的context
      ctx, cancel := context.WithTimeout(context.Background(), timeout)
      go func() {
                // 如果方法执行完成了,则理解取消ctx执行,避免无效等待
                defer cancel()

                // 执行业务操作,修改成自己的代码
                time.Sleep(2 * time.Second)
                fmt.Println("goroutine exec finished")
      }()

      // 等待执行完成,或超时
      <-ctx.Done()
      return
}

// ErrorDoJob 错误执行超时协程例子
// 这里传入了value的引用方式,即使ErrorDoJob超时返回,
// 但里面但协程本身还在执行,还会继续修改value的值。
func ErrorDoJob(timeout time.Duration, value *int) {
      // 定义一个包含超时时间的context
      ctx, cancel := context.WithTimeout(context.Background(), timeout)
      go func() {
                defer cancel()

                // 执行业务操作,修改成自己的代码
                time.Sleep(2 * time.Second)
                *value = 10
                fmt.Println("goroutine exec finished")
      }()

      <-ctx.Done()
      return
}

// RightDoJob 正确执行超时协程的例子,虽然超时执行后协程还在执行,但结果不会返回给调用方了。
func RightDoJob(timeout time.Duration) int {
      value := 0
      // 定义一个包含超时时间的context
      ctx, cancel := context.WithTimeout(context.Background(), timeout)
      go func() {
                defer cancel()

                // 执行业务操作,修改成自己的代码
                time.Sleep(2 * time.Second)
                value = 10
                fmt.Println("goroutine exec finished")
      }()
      <-ctx.Done()

      return value
}

func main() {
      // 【1】执行一个方法,最多等待3秒钟
      DoJob(3 * time.Second)

      // 【2】执行一个方法,并获取方法的返回值,最多等待3秒钟,
      rightValue := RightDoJob(1 * time.Second)
      fmt.Printf("rightValue is %d\n", rightValue)
      // rightValue is 0
      // 再等待一会,看rightValue值是否会发生变化
      time.Sleep(3 * time.Second)
      fmt.Printf("after rightValue is %d\n", rightValue)
      // after rightValue is 0

      // 【3】执行一个方法,并获取方法的返回值,最多等待3秒钟,
      errorValue := 0
      ErrorDoJob(1*time.Second, &errorValue)
      fmt.Printf("errorValue is %d\n", errorValue)
      // errorValue is 0
      // 再等待一会,看errorValue值是否会发生变化
      time.Sleep(3 * time.Second)
      fmt.Printf("after errorValue is %d\n", errorValue)
      // after errorValue is 10
}

页: [1]
查看完整版本: golang:使用context控制协程goroutine运行超时时间