go: Concurrent records processing with channels

Let’s say we have list of records, which can be processed concurrently. Processing time can be different. In example below processing time depends on two parameters. There are used non buffered input and output channels. 

There are these steps:

  1. Submitting N go routines
  2. Writing N times into input channel
  3. Reading N times from output channel. This takes time of the longest go routine.
  4. Display updated records
// version 3 https://play.golang.org/p/2zU0ttZ9ZYn
// version 2 https://play.golang.org/p/qQ8bgVh-dwx (this one)
// version 1 https://play.golang.org/p/LKwVh8d44GQ
package main
import (
"fmt"
"time"
)
const timeFormat = "15:04:05"
type Record = struct {
name string
student bool
delay int //Seconds
}
type InpType = struct {
index int
nameLength int
student bool
}
type OutType = struct {
index int
duration int
}
var records = []Record{
Record{name: "Adam", student: true},
Record{name: "Bob", student: true},
Record{name: "Carl", student: false},
Record{name: "Dick", student: false},
Record{name: "Elisabeth", student: false},
}
func processName(inp <-chan InpType, out chan<- OutType) {
a := <-inp
duration := a.nameLength
if a.student {
duration += 10
}
b := OutType{index: a.index, duration: duration}
time.Sleep(time.Duration(duration) * time.Second)fmt.Printf("%s End of processing index %d\n", time.Now().Format(timeFormat), a.index)out <- b
}
func main() {
fmt.Println(Let's say we are going to process name records.Processing time(delay) in seconds depends on name length, and students take 10 s more.)
inp := make(chan InpType)
out := make(chan OutType)
for i := range records { _ = i go processName(inp, out)}var inpRec InpTypefor i, rec := range records { inpRec = InpType{index: i, nameLength: len(rec.name), student: rec.student} fmt.Printf("%s Channel input: %+v\n", time.Now().Format(timeFormat), inpRec) inp <- inpRec}
for i := range records { _ = i result := <-out records[result.index].delay = result.duration}
fmt.Printf("\nRecords after processing by go routines:\n")for i, rec := range records { fmt.Printf("%d: %+v\n", i, rec)}

}

Here is output:


Let's say we are going to process name records.
Processing time(delay) in seconds depends on name length, and students take 10 s more.

23:00:00 Channel input: {index:0 nameLength:4 student:true}
23:00:00 Channel input: {index:1 nameLength:3 student:true}
23:00:00 Channel input: {index:2 nameLength:4 student:false}
23:00:00 Channel input: {index:3 nameLength:4 student:false}
23:00:00 Channel input: {index:4 nameLength:9 student:false}
23:00:04 End of processing index 3
23:00:04 End of processing index 2
23:00:09 End of processing index 4
23:00:13 End of processing index 1
23:00:14 End of processing index 0

Records after processing by go routines:
0: {name:Adam student:true delay:14}
1: {name:Bob student:true delay:13}
2: {name:Carl student:false delay:4}
3: {name:Dick student:false delay:4}
4: {name:Elisabeth student:false delay:9}
This entry was posted in golang, workday. Bookmark the permalink.

Leave a Reply