Golang:等待x次,然后再循环,而不启动新的goroutine

时间:2017-12-20 15:30:28

标签: go time

我有一个循环,需要等待一段随机的时间再循环。

我有什么:

for {
    rand.Seed(time.Now().UnixNano())
    r := rand.Int()
    //Do stuff
    t, _ := time.ParseDuration(string(r) + "ms")
    time.Sleep(t)
}

不幸的是,循环运行多次,就像time.Sleep无法正常工作一样。

2 个答案:

答案 0 :(得分:4)

您应该检查当前从t, _ := time.ParseDuration丢弃的错误:您传递给Sleep的time.Duration是否为零值,这会导致该函数休眠0纳秒。

更改#1:处理错误

    t, err := time.ParseDuration(string(r) + "ms")
    if err != nil {
        log.Println(err)
        return
    }

导致:

time: invalid duration �ms

由于你是直接将一个整数转换为一个字符串,你正在搞乱你不想要的大量unicode逻辑。

更改#2:使用strconv

    t, err := time.ParseDuration(strconv.Itoa(r) + "ms")
    if err != nil {
        log.Println(err)
        return
    }

结果:

time: invalid duration 7936209096285811603ms

您收到此错误是因为time.Duration使用int64表示存储纳秒。您正尝试传递表示MILLIseconds的int:大部分时间都会溢出。

更改#3:直接指定持续时间

for {
    rand.Seed(time.Now().UnixNano())
    r := rand.Int()
    log.Println(r)
    d := time.Duration(r)
    time.Sleep(d)
}

现在它有效!我的函数生成的第一个整数是649508928394582529,我将其转换为time.Duration(再次,这是纳秒的int64。 这大概是649508928秒:只需一周多。

看起来很多。但请记住,您尝试使用生成的int作为毫秒:这是10 ^ 6倍。

变化#4:循环外的种子

虽然我们正在努力,但让我们稍微改善一下:

rand.Seed(time.Now().UnixNano())
for {
    r := rand.Int()
    log.Println(r)
    d := time.Duration(r)
    time.Sleep(d)
}

说明:伪随机数生成器是状态机。你必须给它喂一次种子,然后它将永远地工作。每次运行它时都给它一个不同的种子不会改善它的随机性:它在可预测的值(时间)上反复应用相同的算法。您可以直接使用time.Now()Unix()

来实现相同的随机性

答案 1 :(得分:0)

除非你在循环中明确地执行,否则

for循环不会产生新的goroutine。默认情况下,下一个循环仅在之前完成后才开始。所以你不需要任何延迟。只需确保您的周期中不使用go关键字。

如果你想发布goroutines:

for {
    rand.Seed(time.Now().UnixNano())
    r := rand.Int()
    //Do stuff in separate goroutine
    go DoStuff()
    t, _ := time.ParseDuration(string(r) + "ms")
    time.Sleep(t)
}

这样就可以推出新的goroutine。