douquqiang1513 2017-08-07 09:54
浏览 27
已采纳

如何限制goroutine

I'm developing a gmail client based on google api.

I have a list of labels obtained through this call

r, err := s.gClient.Service.Users.Labels.List(s.gClient.User).Do()

Then, for every label I need to get details

for _, l := range r.Labels {
    d, err := s.gClient.Service.Users.Labels.Get(s.gClient.User, l.Id).Do()
}

I'd like to handle the loop in a more powerful way so I have implemented a goroutine in the loop:

ch := make(chan label.Label)

for _, l := range r.Labels {

    go func(gmailLabels *gmailclient.Label, gClient *gmail.Client, ch chan<- label.Label) {

        d, err := s.gClient.Service.Users.Labels.Get(s.gClient.User, l.Id).Do()

        if err != nil {
            panic(err)
        }

        // Performs some operation with the label `d`
        preparedLabel := ....

        ch <- preparedLabel

    }(l, s.gClient, ch)
}

for i := 0; i < len(r.Labels); i++ {
    lab := <-ch
    fmt.Printf("Processed %v
", lab.LabelID)
}

The problem with this code is that gmail api has a rate limit, so, I get this error:

panic: googleapi: Error 429: Too many concurrent requests for user, rateLimitExceeded

What is the correct way to handle this situation?

  • 写回答

1条回答 默认 最新

  • drtzb06222 2017-08-07 10:08
    关注

    How about only starting e.g. 10 goroutines and pass the values in from one for loop in another go routine. The channels have a small buffer to decrease synchronisation time.

    chIn := make(chan label.Label, 20)
    chOut := make(chan label.Label, 20)
    
    for i:=0;i<10;i++ {
        go func(gClient *gmail.Client, chIn chan label.Label, chOut chan<- label.Label) {
    
            for gmailLabels := range chIn {
                d, err := s.gClient.Service.Users.Labels.Get(s.gClient.User, l.Id).Do()
    
                if err != nil {
                    panic(err)
                }
    
                // Performs some operation with the label `d`
                preparedLabel := ....
    
                chOut <- preparedLabel
    
            }
    
        }(s.gClient, chIn, chOut)
    
    }
    
    go func(chIn chan label.Label) {
        defer close(chIn)
        for _, l := range r.Labels {
            chIn <- l
        }
    }(chIn)
    
    for i := 0; i < len(r.Labels); i++ {
        lab := <-chOut
        fmt.Printf("Processed %v
    ", lab.LabelID)
    }
    

    EDIT:

    Here a playground sample.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?