How to create a producer and consumer in Go
Overview
The Producer-Consumer problem is an operating system problem. Here, the producer produces a message and passes it to the buffer. The consumer stores that message from the buffer and removes it from the buffer.
For better understanding, let’s explore an illustration.
Explanation
In the illustration above, we have a producer that passes the data to a buffer. The consumer stores that data and removes it from the buffer.
Let's look at an example to learn its implementation in Go.
Example
package mainimport ("runtime/pprof""flag""log""fmt""runtime""os")// Producer definitiontype Producer struct {text *chan intdone *chan bool}// produce start creating message and send it through channelfunc (p *Producer) produce(max int) {fmt.Println("Producer start message sending")for i := 0; i < max; i++ {fmt.Println("Message send by Producer ", i)*p.text <- i}*p.done <- true // updates when message producedfmt.Println("Producer message ends")}type Consumer struct {text *chan int}// consume reads the text channelfunc (c *Consumer) consume() {fmt.Println("consumer start recieving message")for {message := <-*c.textfmt.Println("Message recieved by consumer", message)}}func main() {// profile flagscpuflag := flag.String("cpuflag", "", "update cpu profile to `file`")memflag := flag.String("memflag", "", "update memory profile to the `file`")// Get the max number from flagmax := flag.Int("n", 4, "Show message count")flag.Parse()// To create the maximum number of cores in the processorruntime.GOMAXPROCS(runtime.NumCPU())// CPU Profile creationif *cpuflag != "" {f, err := os.Create(*cpuflag)if err != nil {log.Fatal("Enable to create CPU profile: ", err)}if err := pprof.StartCPUProfile(f); err != nil {log.Fatal("Enable to start CPU profile: ", err)}defer pprof.StopCPUProfile()}var text = make(chan int) // channel send its messagesvar done = make(chan bool) // channel to intimate when production is done//creating a Producer//Start a goroutine for Produce.produceproducer := &Producer{text: &text, done: &done}go producer.produce(*max)//creating a Consumer//Start a goroutine for Consumer.consumeconsumer := &Consumer{text: &text}go consumer.consume()// End the program when the production is complete<-done// Memory profile creationif *memflag != "" {f, err := os.Create(*memflag)if err != nil {log.Fatal("Enable to create memory id: ", err)}runtime.GC() // get update on statusif err := pprof.WriteHeapProfile(f); err != nil {log.Fatal("Enable to write memory id: ", err)}f.Close()}}
Explanation
- Lines 3–9: We import the
runtime/pprof,flag,log,fmt,runtime, andospackages. - Lines 16–19: We create a channel of the
intandbooltypes for theProducerto transfer data using thechankeyword. - Lines 22–30: We create a function,
produce, to send messages to consumers. We terminate it on the*p.done <-truecondition. - Lines 33–35: We create an
inttype channel for theConsumerto read the message. - Lines 38–44: We create a function named
consumefor theConsumer, which shows the received messages. - Lines 48–52: We create two flags:
cpuflag: This is to update the CPU profile to the file.memflag: This is to update the memory profile.- Line 54: We use
parse.flagto get the values from the flags. - Line 57: We use
runtime.GOMAXPROCS(runtime.NumCPU())to create the maximum cores from the processor. - Lines 60–69: We use the
ifcondition to implementcpuflagand identify if any error occurs. - Lines 71–72: We declare the
textanddonevariables to send a message and get an intimation on sending the message. - Lines 76–77: We create a variable,
Producer, and call theProducerfunction. - Lines 81–82: We create a variable,
Consumer, and call theConsumerfunction. - Line 85: We use
<-doneto end the program from the producer's side. - Lines 88–99: We use the
ifcondition to implementmemflagand identify if any error occurs.
Free Resources
Copyright ©2026 Educative, Inc. All rights reserved