Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go中的定时轮询任务_Go - Fatal编程技术网

Go中的定时轮询任务

Go中的定时轮询任务,go,Go,我编写了一些代码,可以每30分钟并发轮询URL: func (obj * MyObj) Poll() { for ;; { for _, url := range obj.UrlList { //Download the current contents of the URL and do something with it } time.Sleep(30 * time.Minute) } //Start the

我编写了一些代码,可以每30分钟并发轮询URL:

func (obj * MyObj) Poll() {
    for ;; {
        for _, url := range obj.UrlList {
            //Download the current contents of the URL and do something with it
        }
        time.Sleep(30 * time.Minute)
}

//Start the routine in another function
go obj.Poll()
然后,我将如何在代码的其他地方添加到obj.urlist中,并确保下次轮询URL时,轮询goroutine中的urlist也已更新,因此也将轮询新的URL


我知道在Go中,内存是通过通信共享的,而不是通过通信共享的,我已经研究了通道,但是我不确定如何在本例中实现它们。

这是一个未经测试但安全的模型,用于定期获取一些URL,能够安全地将新URL动态添加到URL列表中。读者应该清楚地知道,如果您还想删除URL,需要做什么

// Type with queue through a channel.
type MyType struct {
    queue chan []*net.URL
}

func (t *MyType) poll() {
    for urls := range t.queue {
        ...
        time.Sleep(30 * time.Minute)
    }
}

// Create instance with buffered queue.
t := MyType{make(chan []*net.URL, 25)}

go t.Poll()
type harvester struct {
    ticker *time.Ticker // periodic ticker
    add    chan string  // new URL channel
    urls   []string     // current URLs
}

func newHarvester() *harvester {
    rv := &harvester{
        ticker: time.NewTicker(time.Minute * 30),
        add:    make(chan string),
    }
    go rv.run()
    return rv
}

func (h *harvester) run() {
    for {
        select {
        case <-h.ticker.C:
            // When the ticker fires, it's time to harvest
            for _, u := range h.urls {
                harvest(u)
            }
        case u := <-h.add:
            // At any time (other than when we're harvesting),
            // we can process a request to add a new URL
            h.urls = append(h.urls, u)
        }
    }
}

func (h *harvester) AddURL(u string) {
    // Adding a new URL is as simple as tossing it onto a channel.
    h.add <- u
}
类型收割机结构{
ticker*time.ticker//周期性ticker
添加chan字符串//新建URL频道
URL[]字符串//当前URL
}
func newHarvester()*收割机{
rv:=&收割机{
股票代码:time.NewTicker(time.Minute*30),
加:制造(成串),
}
去旅行
返回rv
}
func(h*收割机)运行(){
为了{
挑选{

case如果您需要定期轮询,则不应使用
time.Sleep,而应使用a(或类似)原因是,睡眠只是一种睡眠,不考虑由于您在循环中所做的实际工作而产生的漂移。相反,股票行情器有一个单独的goroutine和一个通道,它们一起能够向您发送常规事件,从而导致一些有用的事情发生

这里有一个和你类似的例子,我加入了一个随机抖动来说明使用股票代码的好处

package main

import (
    "fmt"
    "time"
    "math/rand"
)

func Poll() {
    r := rand.New(rand.NewSource(99))
    c := time.Tick(10 * time.Second)
    for _ = range c {
        //Download the current contents of the URL and do something with it
        fmt.Printf("Grab at %s\n", time.Now())
        // add a bit of jitter
        jitter := time.Duration(r.Int31n(5000)) * time.Millisecond 
        time.Sleep(jitter)
    }
}

func main() {
    //go obj.Poll()
    Poll()
}

当我运行此程序时,我发现尽管存在抖动,但它仍保持严格的10秒周期。

即使t.queue在30分钟内没有更新,可能仍会触发轮询?事实上,是time.Sleep()是不必要的。通道上的范围将阻塞,直到值可用为止,或者在通道关闭后将退出。不过,我会使用一个简单的chan*net.URL,而不是slice,否则您将需要一个内部for循环(覆盖从通道接收的slice)。是的,这是一个快速的破解。;)它在每次轮询和具有空队列的块之间休眠30分钟。真正的解决方案将在内部使用select,如果队列为空,则在其中使用默认值。休眠应在该分支中完成,以便在数据可用时通道接收工作,否则整个循环都需要小睡。您可能会ind interest.Updated talk link(仍然有效,只是删除了
.article
,奇怪的是它返回了一个纯文本):这工作非常出色,尽管您需要将h.ticker.C更改为Great,但我很高兴它起作用了,而且很清楚您可以解决这个bug(我刚刚根据您的规范修复了这个bug)。