How would you organize your goroutine and channel? (P1)

client := &http.Client{
Timeout: 3 * time.Second,
}
go func() {
res, err := client.Post("http://example.com", "application/json", bytes.NewReader([]byte("data")))
...
}()
// we ignore closing response body
go client.Post("http://example.com", "application/json", bytes.NewReader([]byte("data")))
type (
work struct {
query string
}
result struct {
answer string
}
)
var (
workc = make(chan work, 4)
resultc = make(chan result, 4)
errc = make(chan error, 4)
)
// Run result collector in background
go func() {
for {
select {
case r := <-resultc:
processResult(r)
case err := <-errc:
log.Println(err)
default:
}
}
}()
// Run 4 workers in background
for i := 0; i < 4; i++ {
go func() {
for {
select {
case w := <- workc:
r, err := processWork(w)
if err != nil {
errc <- err
continue
}
resultc <- r
default:
}
}()
}
// Combine result and error
type result struct {
answer string
err error
}
// Updated result collector
go func() {
for {
select {
case r := <-resultc:
if r.err != nil {
log.Println(err)
continue
}
processResult(r)
default:
}
}
}()
// Updated workers
for i := 0; i < 4; i++ {
go func() {
for {
select {
case w := <- workc:
resultc <- processWork(w)
default:
}
}()
}
type (
work1 struct {
query string
}
work2 struct {
command int
}
result1 struct {
answer string
err error
}
result2 struct {
output int
err error
}
)
var (
workc1 = make(chan work1, 4)
workc2 = make(chan work2, 4)
resultc1 = make(chan result1, 4)
resultc2 = make(chan result2, 4)
)
// Result collector listens to 2 result channels
go func() {
for {
select {
case r := <-resultc1:
if r.err != nil {
log.Println(err)
continue
}
processResultType1(r)
case r := <-resultc2
if r.err != nil {
log.Println(err)
continue
}
processResultType2(r)
default:
}
}
}()
// 4 workers listen to 2 working channels
for i := 0; i < 4; i++ {
go func() {
for {
select {
case w := <- workc1
resultc1 <- processWorkType1(w)
case w := <- workc2
resultc2 <- processWorkType2(w)
default:
}
}()
}
type work struct {
typ int
query string
command int
err error
}
type result struct {
typ int
answer string
output int
err error
}
type (
work1 struct {
query string
}
work2 struct {
command int
}
result1 struct {
answer string
}
result2 struct {
output int
}
message struct {
work1
work2
result1
result2
typ int
err error
}
)
var (
workc = make(chan message, 8)
resultc = make(chan message, 8)
)
// Updated collector logic
go func() {
for {
select {
case msg := <-resultc:
if msg.err != nil {
log.Println(err)
continue
}
switch msg.typ {
case 1:
processResultType1(msg.result1)
case 2:
processResultType2(msg.result2)
}
default:
}
}
}()
// Updated workers logic
for i:= 0; i < 4; i++ {
go func() {
for {
select {
case msg := <- workc:
switch msg.typ {
case 1:
resultc <- processWorkType1(msg.work1)
case 2:
resultc <- processWorkType2(msg.work2)
}
default:
}
}()
}

--

--

--

https://twitter.com/owlwalks

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Moving to Microservices

Function Prototype in C

Pusuke Weekly update Mar 27

Learn Kubernetes: Job — Create a parallel job

How to make a fetch call to the back-end. (Ruby on Rails, React)

A step by step guide on how to use Nav-graph Scoped ViewModels

Azure — Organize and Manage Multiple Azure Subscriptions and Resources with Management Groups

WEB 2.0 vs WEB 3.0

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Khoa Pham

Khoa Pham

https://twitter.com/owlwalks

More from Medium

In conversation with ProtocolBuffers

Battle of Concurrency | Goroutines vs Threads.

You should Unit Test your API endpoints, it’s easy!

Getting started with GO Programming Language — Part Two