WithTimeout 超時自動取消方法,當執行一個go 協程時,超時自動取消協程
package main
import (
"fmt"
"time"
"context"
)
func main() {
ctx, _ := context.WithTimeout(context.Background(), 5 * time.Second)
fmt.Println("start at ", time.Now().Format("2006-01-02 15:04:05"))
go func() {
defer func() {
fmt.Println("goroutine exit ", time.Now().Format("2006-01-02 15:04:05"))
}()
for {
select {
case <-ctx.Done(): // 因為ctx帶超時參數,當時間期限到了之后就會走到這里退出協程
fmt.Println("Done. ", time.Now().Format("2006-01-02 15:04:05"))
return
default: // 協程循環執行for,當ctx.Done()無信號時總是走到Default分支
fmt.Println("case default ", time.Now().Format("2006-01-02 15:04:05"))
time.Sleep(time.Second)
}
}
}()
time.Sleep(20 * time.Second) // 主程序用sleep阻塞住
fmt.Println("stop at ", time.Now().Format("2006-01-02 15:04:05"))
}
在使用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
}
需要搭配接收ctx.Done()消息,超時才能退出。