为了账号安全,请及时绑定邮箱和手机立即绑定

Golang:油门(延时)功能在 goroutine 中不起作用(在主线程中工作正常)

Golang:油门(延时)功能在 goroutine 中不起作用(在主线程中工作正常)

Go
白板的微信 2021-09-13 15:39:52
所以我正在编写一个实用程序来查询工作中的 API,它们每 10 秒限制为 20 次调用。很简单,我只会将我的通话限制在自上次通话以来至少过去 0.5 秒。在我尝试使用 goroutines 之前,我的 Throttle 实用程序运行良好。现在我正在使用结构/方法组合:func (c *CTKAPI) Throttle() {if c.Debug{fmt.Println("\t\t\tEntering Throttle()")}for { //in case something else makes a call while we're sleeping, we need to re-check    if t := time.Now().Sub(c.LastCallTime); t < c.ThrottleTime {        if c.Debug{fmt.Printf("\t\t\tThrottle: Sleeping %v\n", c.ThrottleTime - t)}        time.Sleep(c.ThrottleTime - t)    } else {        if c.Debug{fmt.Println("\t\t\tThrottle: Released.")}        break    }}c.LastCallTime = time.Now()if c.Debug{fmt.Println("\t\t\tExiting Throttle()")}}然后我在每个 goroutine 中的每次调用之前调用 what.Throttle() 以确保在启动下一个调用之前我已经等待了至少半秒。但这似乎不可靠并且会产生不可预测的结果。有没有更优雅的方式来限制并发请求?-麦克风
查看完整描述

3 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

实际上有一个更简单的方法来做到这一点:创建一个时间行情。


package main


import (

    "fmt"

    "sync"

    "time"

)


func main() {

    rateLimit := time.Tick(500 * time.Millisecond)

    <-rateLimit


    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {

        wg.Add(1)

        go func(i int) {

            <-rateLimit

            fmt.Println("Hello", i)

            wg.Done()

        }(i)

    }

    wg.Wait()

}


查看完整回答
反对 回复 2021-09-13
?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

因为您正在引入数据竞争,所以多个例程正在访问/更改 c.LastCallTime。

您可以time.Tick改用或制作c.LastCallTime一个int64c.LastCallTime = time.Now().Unix()) 并用于atomic.LoadInt64/StoreInt64检查它。


查看完整回答
反对 回复 2021-09-13
  • 3 回答
  • 0 关注
  • 167 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信