Looking at your code and your question/requirement: Stay in order as the original go channel delivered the data.Staying in sync and still firing off multiple go routines to process the data, could be done like this:
func processStatements(mysqlChan chan *instructions) { var wg sync.WaitGroup prevOp := "" // Previous operation for { op, open := <-mysqlChan if !open { break } if prevOp!=op.Operation { // Next operation type, unknown side effects on previous operations, // wait for previous to finish before continuing wg.Wait() } switch op.Operation { case "i": wg.Add(1) go processInsert(op,wg) break case "u": wg.Add(1) go processUpdate(op,wg) break case "d": wg.Add(1) go processDelete(op,wg) break case "c": break } prevOp = op.Operation } // Previous go routines might still be running, wait till done wg.Wait() // Close any channels}func processInsert(c chan *sqlCall,wg *sync.WaitGroup) { defer wg.Done() // Do actual insert etc}
The main differences with your program are:
- Processing is in order, safe against your base scenario
- Process of next operation type will wait until previous operation type is finished
- Multiple of the same operations run in parallel (as for in your code a single operation per type would run in parallel). Depending on the data distribution either of them can be faster or slower (i,i,i,d,u = 3 waits in this code, while it would also be 3 waits in your code, however in your code the 3 i would run sequential, here they run parallel) (Look into insert or update for mysql, since now your inserts could suddenly be updates depending on your data).