Search code examples
gochannelgoroutine

How to receive data from multiple channels in sequence?


I am currently trying to receive data from two channels using a select statement.

select {
    case msg1 := <-ch1:
        // send to another channel
    case msg2 := <-ch2:
        // send to another channel
}

The format of the data received from the above two channels is as follows.

type msg struct {
    msgId uint32
    data []byte
}

What I want is to compare the msg received from two channels with msgId and send msg to another channel in order.

Is the only way to achieve my goal is to use sync.Mutex to use the data structure Queue?

Is there a way to send the data sent through a channel from multiple goroutines back to another channel in order?

EDIT: The data coming from the two channels is sorted as long as the order is correct. Data is not transmitted in a completely jumbled order.


Solution

  • You can construct an ordering algorithm that buffers out-of-order messages like this:

    // Buffer to keep out-of-order messages
    buffer:=make(map[uint32]msg)
    // id of the next expected message
    nextExpected:=1 
    for {
      select {
          case m:=<-ch1:
            buffer[m.id]=m
          case m:=<-ch2:
            buffer[m.id]=m
      }
      // If the next expected message is received, send it
      for {
         if m,ok:=buffer[nextExpected]; ok {
            result<-m
            delete(buffer,nextExpected)
            nextExpected++
         } else {
            break
         }
      }
    }