How to Gracefully Terminate Go Routines

The beauty lies in the simplicity of your mind.

First words, I love Go routines.

I love the way everything falls together. How after all the thinking and designing. The final code just looks so elegant and simple.

The Art

Go handles things by channels. Think of it like lines of communication between Go routines (from here I shall refer to them as Gophers).


I have a background in electronics, I tend to imagine these gophers as separate process working independently then talk to each other through the small electrical wires (channels).

When you imagine your program like that. Your brain naturally avoid the situation when many wires cross each other and make the wrong signals. As in situation when there are many ways of reasoning on the same subjects.

Don’t communicate by sharing memory; share memory by communicating. (R. Pike)

By learning Go, I also find out that I naturally get into the style of Domain Driven Development. It feels like those Gophers have their own world, they respect each other, give each other space to perform then share the result and the stage through a nice clear line of communication.

The Goal

Back to our topic, I stumbled on a little problem of terminating our service with a cleaning process.

When we run a long running service we often want to have the process gratefully terminated. Which means when receiving the terminate signal it needs to finish the pending tasks like clean up database or closing connections.

The Solution

First we create a os.Signal channel to tell others the TERMinate or INTerupt signals.

Next are the stop and stopped channels. As you may have guessed, the first is for the os.Signal to tell doWork to stop. And the second is for our doWork process to inform back that it is gracefully stopped.

Then inside the function we have the context WithCancel. This context has a special ability (read function) to cancel() when we want it to. In this case we begin to cancel right after the stop signal is fired.

Inside doWork, it is just a simple anonymous gopher to continuous listening to the context Done() to spin up the cleanup progress then close the stopped channel, in turn finish the main gopher.

Final words

By tackling this small task, I can feel the simplicity of Go lang.

This article is heavily inspired by this Mat Ryer post. I try to implement the idea in my own way to further understanding the concept.

Hope this can help you through your journey to the way of Go.

Programming with passion to understand how everythings fit together.

Programming with passion to understand how everythings fit together.