【问题标题】:Select from slice of channels(sending to a free channel)?从频道片中选择(发送到免费频道)?
【发布时间】:2019-08-01 06:01:34
【问题描述】:

我正在发出多个 http 请求:

    type item struct{
       me []byte
    }
    items := getItems()
    for _, me := range items {
          me.save()
    }

为了有效地做到这一点,我用 go rutines 来做,我的第一个方法是让它像一个 go rutines 池:

    items := getItems()
    var wg sync.WaitGroup
    wg.Add(len(items))
    for _, me := range items {
        go func(me item) {
            me.save()
            wg.Done()
        }(me)
    }
    wg.Wait()

但他们都尝试同时发出 http 请求,其中一些失败,因为我的带宽无法处理所有这些请求。 所以我尝试使用select 代替频道:

    channel1 := make(chan item)
    channel2 := make(chan item)
    channel3 := make(chan item)
    var wg sync.WaitGroup
    items := getItems()
    wg.Add(len(items))
    go func() {
        for me := range channel1 {
            me.save()
            wg.Done()
        }
    }()
    go func() {
        for me := range channel2 {
            me.save()
            wg.Done()
        }
    }()
    go func() {
        for me := range channel3 {
            me.save()
            wg.Done()
        }
    }()
    for _, me := range items {
        select {
        case channel1 <- me:
        case channel2 <- me:
        case channel3 <- me:
        }
    }

但是添加更多的 go rutines 以找到我的带宽可以处理的最大 go rutines,我的代码变得越来越大,我尝试这样做:

    max:=7
    var channels []chan item
    for i:=0;i<max;i++{
        channel=make(chan item)
        channels=append(channels,channel)
    }
    for _, me := range items {
        select {
            //???????????????
        }
    }

但我不确定如何将其作为最后一种方法

还请记住,“从频道片段中选择”是一个已经提出的问题,但他们的答案只有在 select 正在监听哪个频道先到达时,在我的情况下,我希望 Select 发送任何免费频道,所以不一样

【问题讨论】:

  • 这是一种……不寻常的实现工作池的方式。为什么不是“标准”方式:一个任务队列,它是一个 [缓冲] 通道和几个工作 goroutine?
  • 我试过了,但我做不到,你能举个例子吗?
  • 是的,我正在努力寻找一篇关于我不久前阅读的主题的好博文。
  • 啊,在这里,看看:marcio.io/2015/07/…。看来作者确实被频道迷住了,但在 cmets 中也有一些很好的提示。

标签: go channel


【解决方案1】:

我的方法有误,答案很简单 worker pools

type item struct {
    me []byte
}

func worker(canalFiles <-chan item, wg *sync.WaitGroup) {
    for file := range canalFiles {
        file.save()
        wg.Done()
    }
}
func main() {
    var wg sync.WaitGroup
    items := getItems()
    wg.Add(len(items))
    canalFiles := make(chan item)
    for i := 0; i < 8; i++ {
        go worker(canalFiles, &wg)
    }
    for _, file := range items {
        canalFiles <- file
    }
    fmt.Printf("waiting.....")
    wg.Wait()
}


【讨论】:

    【解决方案2】:

    您可以使用reflect.Select,使用Dir=SelectSend 创建一个SelectCase 结构的切片,如下所示:

    max:=7
    var channels []chan item
    for i:=0;i<max;i++{
        channel=make(chan item)
        channels=append(channels,channel)
    }
    for _, me := range items {
        cases := make([]reflect.SelectCase, max)
        for j := 0; j < max; j++ {
            cases[j] = reflect.SelectCase{
                Dir: reflect.SelectSend,
                Chan: reflect.ValueOf(channels[j]),
                Send: reflect.ValueOf(me)
            }
        }
        reflect.Select(cases)
    }
    

    【讨论】:

    • 我一直在寻找类似的东西,但事实证明我的方法有误,最后我做了一个worker pool
    猜你喜欢
    • 2016-06-07
    • 2020-07-16
    • 2019-05-11
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 2019-04-15
    相关资源
    最近更新 更多