Question: Can you write code implementing the consumer and producer pattern?
This is a classic concurrency problem where we have threads generating data to be consumed (producers) by other threads (consumers).
The implementation with POSIX threads can be a pain in the ass but it is quite straight forward in golang thanks to its concurrency constructs.
Here is some code, heavily commeted for those coming from other programming languages.
package main // Tell go runtime your main lives here
import ("fmt") // We need the fmt package to print to the stdout
/*
These next two lines create two new channels, which are
one of the concurrency constructs golang offers.
The first channel is a boolean channel the second one is
an int channel. We can read or write data to the channels.
We will see how shortly.
*/
var done = make(chan bool)
var msgs = make(chan int)
/*
In our main function, we spawn two go routines. go routines
are cheap functions that will be run concurrently by go runtime.
They are just regular functions, but using the keyword go before
a function call we can run them as go routines.
So those two functions will run concurrently.
Finally we block the main thread by reading from the done channel.
As soon something comes down the channel, we read it, toss it and
the main thread continues executing. In this case we exit the
program.
*/
func main () {
go produce()
go consume()
<- done
}
/*
The produce go routine (or function) loops 10 times
and writes an integer (0..10) in the msg channel.
Notice that we will block until someone (the consumer)
reads form the other side of the channel.
Once we are done, we send a boolean on the done channel
to let the main go routine that we are done.
*/
func produce() {
for i := 0; i < 10; i++ {
msgs <- i
}
done <- true
}
/*
The consume go routine loops infinitely and reads
on the msgs channel. It will block until something
comes in the channel.
The syntax can be a little bit strange for people
coming from other languages.
':=' creates a variable assigning it the type of the value
coming on the right of the assignation. An int in this
case.
'<-' is the go way to read from a channel.
Once we have the msg (int) we dump it in the stdout.
*/
func consume() {
for {
msg := <-msgs
fmt.Println(msg)
}
}
Yup... It demonstrates a producer-consumer pattern that is imperfect because not all of the produced items will be consumed before the application terminates. The issue is that not all of the produced items will be consumed because main() is waiting for a signal on the done channel, which producer sends when it is done. Producer will be expected to terminate sooner than the consumer, so all of the items may not be consumed. So, it is expected that each execution will have different consumption results. Hope this is helpful...