断路器设计模式 sleep vs time.AfterFunc

我正在尝试创建一个断路器模式,我想执行一个命令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适用于上面的代码,但不适用于下面的示例,我必须用 a 替换它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因此想知道使用and之间有什么区别,time.Sleep以及什么是实现这种模式的最佳方式。


杨魅力
浏览 271回答 1
1回答

MMMHUHU

每当您遇到默认情况时,选择都会立即结束。在上面的示例中,在您执行AfterFuncfor 循环后,将持续运行直到run有项目(3 秒后)。忙碌的等待通常是不好的。使用该sleep解决方案,您永远不会有忙碌的等待,这很好。不过,我不确定我是否完全遵循您在第二个示例中使用嵌套选择来完成的工作。为什么你需要通道和异步?为什么不只是:retryCount := 0for retryCount < 3 {&nbsp; &nbsp;err := doSomethingScary()&nbsp; &nbsp;if err == nil{&nbsp; &nbsp; &nbsp;//success! return results!&nbsp; &nbsp;} else{&nbsp; &nbsp; &nbsp;//failure! wait and retry&nbsp; &nbsp; &nbsp;time.Sleep(time.Second) //time.sleep is a good non-busy wait&nbsp; &nbsp;}}// max tries exceeded. Return error.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go