golang context 超时自动取消方法

WithTimeout 超时自动取消方法,当执行一个go 协程时,超时自动取消协程

package main

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

// 模拟一个最小执行时间的阻塞函数
func inc(a int) int {
    res := a + 1                // 虽然我只做了一次简单的 +1 的运算,
    time.Sleep(1 * time.Second) // 但是由于我的机器指令集中没有这条指令,
    // 所以在我执行了 1000000000 条机器指令, 续了 1s 之后, 我才终于得到结果。B)
    return res
}

// 向外部提供的阻塞接口
// 计算 a + b, 注意 a, b 均不能为负
// 如果计算被中断, 则返回 -1
func Add(ctx context.Context, a, b int) int {
    res := 0
    for i := 0; i < a; i++ {
        res = inc(res)
        select {
        case <-ctx.Done():
            fmt.Println("ctx Done in a")
            return -1
        default:
        }
    }
    for i := 0; i < b; i++ {
        res = inc(res)
        select {
        case <-ctx.Done():
            fmt.Println("ctx Done in b")
            return -1
        default:
        }
    }
    return res
}

func main() {
    // 使用开放的 API 计算 a+b
    a := 1
    b := 2
    timeout := 1200 * time.Millisecond
    ctx, cancel := context.WithTimeout(context.Background(), timeout)
    defer cancel()
    res := Add(ctx, 1, 2)
    fmt.Printf("Compute: %d+%d, result: %d\n", a, b, res)
}

在使用golang开发中,调用外部可执行程序通过exec包是我们常用的方式。如何控制超时请见如下代码:

func CmdWithTimeout(name string, arg ...string) ([]byte, error) {
    //timeout 的值可以放在环境变量里
    timeoutstr, err := strconv.Atoi(os.Getenv("cmd-timeout"))
    if err != nil {
	log.Errorf("fail to load netlink timeout: %v", err)
	return nil, err
    }
    timeoutval := time.Duration(timeoutstr) * time.Millisecond

    ctxt, cancel := context.WithTimeout(context.Background(), timeoutval)
    defer cancel()

    cmd := osexec.CommandContext(ctxt, name, arg...)

    var ret []byte
    ret, err = cmd.CombinedOutput()
    return ret, err
}

在库函数CombinedOutput中会接收commandcontext的ctx.Done()消息,超时退出。

猜你喜欢

转载自www.cnblogs.com/janeysj/p/12809659.html