使用数据库中的映射每隔X秒运行一次代码

时间:2018-07-18 04:29:02

标签: go hashmap

使用golang的时间。NewTicker,我试图运行数据库中的每条记录(由文本和计时器组成,即重复之前的秒数),但它仅重复其抓取的第一条记录

func LoadTimedCommands() map[string]time.Duration {
    database := InitializeDB()

    rows, _ := database.Query("SELECT TimedResponse, Timer from timedcommands")

    com := make(map[string]time.Duration)
    for rows.Next() {
        var TimedResponse string
        var Timer time.Duration
        rows.Scan(&TimedResponse, &Timer)
        com[TimedResponse] = Timer
    }
    return com
}

func TimedCommands(conn net.Conn, channel string, name string) {
    timedcoms := LoadTimedCommands()
    for k, v := range timedcoms {
        for range time.NewTicker(v * time.Second).C {
            BotSendMsg(conn, channel, k, name)
        }
    }
}

因此,如果我有两个记录要使用: Sqlite data

然后,该代码应每15秒运行一次记录,然后每10秒运行第二条记录。但是,再次,仅运行加载到地图中的第一个记录。

1 个答案:

答案 0 :(得分:0)

您的问题出在此功能上

func TimedCommands(conn net.Conn, channel string, name string) {
    timedcoms := LoadTimedCommands()
    for k, v := range timedcoms {
        for range time.NewTicker(v * time.Second).C {
            BotSendMsg(conn, channel, k, name)
        }
    }
}

在本部分中,您rangetime.NewTicker(...).C频道上的位置:

for range time.NewTicker(v * time.Second).C {
    BotSendMsg(conn, channel, k, name)
}

这将尝试从此一个代码行中读取值,直到关闭通道C。这意味着外部循环仅执行一次迭代,然后我们在内部循环上进行阻塞,直到C关闭为止。而且我们永远不会一次创建多个Ticker

您可以通过在自己的goroutine中创建代码来解决此问题:

for k, v := range timedcoms {
    go func(conn net.Conn, channel, name, k string, v time.Duration) {
        for range time.NewTicker(v * time.Second).C {
            BotSendMsg(conn, channel, k, name)
        }
    }(conn, channel, k, v)
}

但是您可能需要进行一些同步,以确保可以停止启动的goroutine,或者确保可以同时从多个goroutine中调用BotSendMsg(...)