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