通过将空结构向下传递到通道Go,停止循环

通过将空结构向下传递到通道Go,停止循环,go,goroutine,poller,Go,Goroutine,Poller,我正在尝试在围棋中创建一个轮询器,它会旋转起来,每24小时执行一个函数 我还希望能够停止轮询,我正试图通过拥有一个done通道并传递一个空结构来停止for循环来停止轮询 在我的测试中,for just无限循环,我似乎无法阻止它,我是否错误地使用了done通道?股票行情行情如预期般运行 Poller struct { HandlerFunc HandlerFunc interval *time.Ticker done chan struct{} } f

我正在尝试在围棋中创建一个轮询器,它会旋转起来,每24小时执行一个函数

我还希望能够停止轮询,我正试图通过拥有一个done通道并传递一个空结构来停止for循环来停止轮询

在我的测试中,for just无限循环,我似乎无法阻止它,我是否错误地使用了done通道?股票行情行情如预期般运行

Poller struct {
    HandlerFunc HandlerFunc
    interval    *time.Ticker
    done        chan struct{}
}

func (p *Poller) Start() error {
    for {
        select {
        case <-p.interval.C:
            err := p.HandlerFunc()
            if err != nil {
                return err
            }
        case <-p.done:
            return nil
        }
    }
}

func (p *Poller) Stop() {
    p.done <- struct{}{}
}

似乎问题出在您的用例中,您在blocking maner中调用了
poller.Start()
,所以永远不会调用
poller.Stop()
。在
go
项目中,在
Start
/
Run
方法中调用goroutine是很常见的,因此,在
poller.Start()
中,我会这样做:

func (p *Poller) Start() <-chan error {
    errc := make(chan error, 1 )

    go func() {
        defer close(errc)

        for {
            select {
            case <-p.interval.C:
                err := p.HandlerFunc()
                if err != nil {
                    errc <- err
                    return
                }
            case <-p.done:
                return
            }
        }
    }

    return errc
}

func(p*Poller)Start()在Go中没有明确的方式来广播事件to Go例程,例如取消。相反,它的惯用做法是创建一个通道,当关闭时表示一条消息,例如取消它必须做的任何工作。这是一种可行的模式:

var done=make(chan结构{})
func取消()布尔{
挑选{

case您可以共享执行此操作的代码吗?显示的源代码看起来不错,问题可能在代码的其他地方。您几乎总是希望
关闭
一个通道以取消。如果您的for循环收到
添加的测试代码,它将返回,谢谢。@pocockn
err:=poller.Start()
正在阻塞。因此从不调用poller.Stop()
。我无法从go func(){}内部返回错误。使用go func()错误{}是惯用方法吗?还是有更好的方法处理p.HandlerFunc()的错误?最好使用单独的通道处理错误。请参阅更新的示例
func (p *Poller) Start() <-chan error {
    errc := make(chan error, 1 )

    go func() {
        defer close(errc)

        for {
            select {
            case <-p.interval.C:
                err := p.HandlerFunc()
                if err != nil {
                    errc <- err
                    return
                }
            case <-p.done:
                return
            }
        }
    }

    return errc
}