我正在尝试创建Circuit breaker pattern,我想执行命令exec.Command,如果失败,请在X定义的时间内重试,出于测试目的,我正在做类似这样的事情测试time.AfterFunc
:
package main
import (
"fmt"
"time"
)
func myFunc() error {
for i := 1; i < 10; i++ {
fmt.Printf("i = %+v\n", i)
if i%3 == 0 {
return fmt.Errorf("error")
}
}
return nil
}
func main() {
run := make(chan struct{}, 1)
run <- struct{}{}
for {
select {
case <-run:
err := myFunc()
if err != nil {
time.AfterFunc(3*time.Second, func() {
run <- struct{}{}
})
}
default:
}
}
}
time.AfterFunc
适用于上述代码,但不适用于以下示例,我必须将其替换为sleep
才能达到预期效果:
package main
import (
"fmt"
"os/exec"
"time"
)
func Exec(done chan<- error) error {
cmd := exec.Command("./start")
if err := cmd.Start(); err != nil {
return err
}
go func() {
done <- cmd.Wait()
}()
return nil
}
func main() {
var (
run = make(chan struct{}, 1)
done = make(chan error, 1)
)
Exec(done)
for {
select {
case <-run:
err := Exec(done)
if err != nil {
fmt.Println(err)
// time.AfterFunc(3*time.Second, func() {
time.Sleep(3 * time.Second)
run <- struct{}{}
}
default:
select {
case err := <-done:
fmt.Println(err)
run <- struct{}{}
}
}
}
}
./sleep
的内容:
#!/bin/sh
sleep 3
为了测试,创建错误,我切换perms:
chmod -x sleep
chmod +x sleep
因此想知道使用time.AfterFunc
和time.Sleep
之间有什么区别,这可能是实现此模式的最佳方式。
答案 0 :(得分:0)
每当您点击默认情况时,选择会立即结束。在上面的示例中,执行AfterFunc
后,for循环会持续运行,直到run
有项目(3秒后)。忙碌的等待通常很糟糕。使用sleep
解决方案,您永远不会有忙碌的等待,这很好。我不确定我是否完全按照第二个例子中的嵌套选择完成了你想要完成的任务。
为什么你需要频道和异步?为什么不呢:
retryCount := 0
for retryCount < 3 {
err := doSomethingScary()
if err == nil{
//success! return results!
} else{
//failure! wait and retry
time.Sleep(time.Second) //time.sleep is a good non-busy wait
}
}
// max tries exceeded. Return error.