我正在开发一个基于 google api 的 gmail 客户端。
我有一个通过这个调用得到的标签列表
r, err := s.gClient.Service.Users.Labels.List(s.gClient.User).Do()
然后,我需要获取每个标签的详细信息
for _, l := range r.Labels {
d, err := s.gClient.Service.Users.Labels.Get(s.gClient.User, l.Id).Do()
}
我想以更强大的方式处理循环,所以我在循环中实现了一个 goroutine:
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\n", lab.LabelID)
}
这段代码的问题是 gmail api 有一个速率限制,所以,我得到这个错误:
panic: googleapi: Error 429: Too many concurrent requests for user, rateLimitExceeded
处理这种情况的正确方法是什么?
最佳答案
如何只开始例如10 个 goroutines 并将值从一个 for 循环传递到另一个 go 例程。 channel 有一个小缓冲区以减少同步时间。
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\n", lab.LabelID)
}
编辑:
这里是playground sample .
关于go - 如何限制goroutine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45544133/