Чтение из нескольких каналов одновременно в Golang

Я новичок в Golang. Прямо сейчас я пытаюсь выяснить, как сделать канал any-to-one в Golang, где настройка выглядит следующим образом:

скажем, у меня есть две goroutines numgen1 и numgen2, выполняющиеся одновременно и записывающие номера в каналы num1 resp. пит2. Я хотел бы добавить числа, отправленные из numgen1 и numgen2 в новом процессе addnum. Я пробовал что-то вроде этого:

func addnum(num1, num2, sum chan int) {
    done := make(chan bool)
    go func() {
        n1 := <- num1
        done <- true
    }()
        n2 := <- num2
        <- done
    sum <- n1 + n2
}

но это, видимо, к сожалению, ошибочные. Кто-нибудь, пожалуйста, дайте мне немного. идеи?

большое спасибо за вашу помощь.

3 ответов


в зависимости от ваших требований, вы можете прочитать и каналов для каждой итерации (т. е. своего рода функция "zip"). Вы можете сделать это с помощью select, аналогично user860302'ы ответ:

func main() {

  c1 := make(chan int)
  c2 := make(chan int)
  out := make(chan int)

  go func(in1, in2 <-chan int, out chan<- int) {
    for {
      sum := 0
      select {
      case sum = <-in1:
        sum += <-in2

      case sum = <-in2:
        sum += <-in1
      }
      out <- sum
    }
  }(c1, c2, out)
}

это работает вечно. Мой предпочтительный способ прекратить goroutines, как этот, - закрыть входные каналы. В этом случае вам нужно будет подождать, пока оба закроются, а затем close(out) перед завершением.

совет: обратите внимание на использование направленные каналы как формальные параметры goroutine. Компилятор улавливает больше ошибок, когда вы пишете его таким образом. Счастье!


самый простой ответ будет

func addnum(num1, num2, sum chan int) {
  n1 := <- num1
  n2 := <- num2
  sum <- n1 + n2
}

так как вам нужно как num1 и num2 сделать расчет, нет смысла делать это иначе. В конце концов, есть два возможных ордера на исполнение:

  1. num1 генерирует число, за которым следует num2
  2. num2 генерирует число, за которым следует num1

в первом случае показания нашего канала точно соответствуют порядку исполнения. Во втором случай, наше первое чтение будет блокировать до num1 наконец произвел число; второе чтение завершится почти мгновенно, потому что num2 канал уже имеет ряд.

если вы хотите узнать больше о каналах в Go, я бы предложил взглянуть на http://godoc.org/github.com/thomas11/csp -- это коллекция примеров CSP Хоара, написанных в Go.


чтобы ответить на вопрос "чтение из нескольких каналов одновременно"

существует способ прослушивания нескольких каналов одновременно:

func main() {

    c1 := make(chan string)
    c2 := make(chan string)

    ...
    go func() {
        for {
            select {
                case msg1 := <- c1:
                fmt.Println(msg1)

                case msg2 := <- c2:
                fmt.Println(msg2)
             }
        }
    }()

в этом примере я создаю канал msg1 и msg2. Затем я создаю процедуру go с бесконечным циклом. В этом цикле я слушаю msg1 и msg2. Эта система позволяет читать на несколько каналов одновременно и обрабатывать сообщения, когда прибывают.

чтобы избежать утечек, я должен вероятно, добавить еще один канал, чтобы остановить горутина.