在这种情况下,我试图编写一个在满足条件时会中断的函数,命令的输出等于某个值(在此示例中为hello),或者 超时
timeout := 10 sec
func run() error {
for {
out , _ := exec.Command("echo", "hello").Output()
if string(out) == "hello" || timeout {
break
}
}
}
我已经看到人们使用select,但是我不知道如何在其中使用它, 有什么提示吗?
答案 0 :(得分:6)
如果命令运行迅速,则可以使用以下简单方法:
deadline := time.Now().Add(10 * time.Second)
for {
out, _ := exec.Command("echo", "hello").Output()
if string(out) == "hello" || time.Now().After(deadline) {
break
}
}
一种改进是使用context with a timeout:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
for {
out, _ := exec.CommandContext(ctx, "echo", "hello").Output()
if string(out) == "hello" || ctx.Err() != nil {
break
}
}
上下文版本将在超时时终止命令。代码将循环直到找到字符串或the context is done。
答案 1 :(得分:3)
您可以使用类似于Go by Example: Timeouts
的代码c2 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c2 <- "result 2"
}()
select {
case res := <-c2:
fmt.Println(res)
case <-time.After(3 * time.Second):
fmt.Println("timeout 2")
}
在您的情况下,go func
将exec
echo
,而main函数将等待超时或go func
的执行,以先到者为准。
即:https://goplay.space/#MtHh3CenMcn
package main
import (
"fmt"
"os/exec"
"time"
)
func main() {
c2 := make(chan string, 1)
go func() {
out, err := exec.Command("echo", "hello").Output()
fmt.Println(err)
c2 <- string(out)
}()
select {
case res := <-c2:
fmt.Println("'" + res + "'")
case <-time.After(3 * time.Second):
fmt.Println("timeout 2")
}
}
如果echo
花费3秒钟以上,超时就会开始。
请注意,该示例不适用于游乐场设置,因为:
"echo": executable file not found in $PATH
但是在您的本地环境中,它应该可以工作。
基于上下文的另一种方法:https://goplay.space/#F2GtMLgVAAI
package main
import (
"context"
"fmt"
"os/exec"
)
func main() {
gen := func(ctx context.Context) <-chan string {
dst := make(chan string)
go func() {
out, err := exec.Command("echo", "hello").Output()
fmt.Println(err)
for {
select {
case <-ctx.Done():
return // returning not to leak the goroutine
case dst <- string(out):
return
}
}
}()
return dst
}
ctx, cancel := context.WithTimeout(context.Background(), 3)
defer cancel() // cancel when we are finished consuming integers
gen(ctx)
}