golang代码实例库

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2531|回复: 0

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

[复制链接]

82

主题

82

帖子

486

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
486
发表于 2022-1-21 00:17:20 | 显示全部楼层 |阅读模式
实例说明
我们很容易启动一个goroutine协程执行指定任务,但如果不控制协程的执行超时时间,很容易造成程序实行超时。
1)通过context控制协程超时时间
2)协程正确返回数据的方式
3)协程错误返回数据的方式,当然有时候这不是一种错误,而是特性。详见代码注释

实例代码
[Golang] 纯文本查看 复制代码
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
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|golang代码实例库 ( 粤ICP备2021162396号 )

GMT+8, 2024-12-5 08:43 , Processed in 0.016484 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表