Go: How Does a Goroutine Start and Exit?

Vincent Blanchon
Apr 1, 2020 · 3 min read
Image for post
Image for post
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

ℹ️ This article is based on Go 1.14.

In Go, a goroutine is nothing but a Go structure containing information regarding the running program, such as stack, program counter, or its current OS thread. The Go scheduler deals with that information to give them running time. The scheduler also has to pay attention at the start and the exit of the goroutines, two phases that need to be managed carefully.

For more information about the stack and the program counter, I suggest you read my article “Go: What a Goroutine Switch Actually Involve?

Start

The process of starting a goroutine is quite simple. Let’s use a program as an example:

Image for post
Image for post

The main function starts a goroutine before printing a message. Since the goroutine will have its own running time, Go notifies the runtime to set up a new goroutine, meaning:

However, the goroutine does not get any runtime immediately. The newly created goroutine will be enqueued at the beginning of the local queue and will run at the next round of the Go scheduler. Here is a diagram of the current state:

Image for post
Image for post

Putting the goroutine at the head of the queue makes it the first to run after the current goroutine. It will run either on the same thread or on another one if any work-stealing happens.

For more information about the work-stealing, I suggest you read my article “Go: Work-Stealing in Go Scheduler.”

The goroutine creation also can be seen in the assembly instructions:

Image for post
Image for post

Once the goroutine is created and pushed onto the local queue of goroutines, it goes directly to the next instructions of the main function.

Exit

When a goroutine ends, Go must schedule another goroutine to not waste the CPU time. It will also keep the goroutine to reuse it later.

You can find more information about the recycling of the goroutine in my article “Go: How Does Go Recycle Goroutines?

However, Go needs a way to be aware of the end of the goroutine. This control is during the creation of the goroutine. While creating the goroutine, Go sets the stack to a function named goexit before setting the program counter to the real function called by the goroutine. This trick forces the goroutine to call the function goexit after ending its work. The following program allows us to visualize it:

Image for post
Image for post

The output will complete the stack trace:

/path/to/src/main.go:16
/usr/local/go/src/runtime/asm_amd64.s:1373

The file asm_amd64 written in assembly contains this function:

Image for post
Image for post

Then, Go will switch to g0 to schedule another goroutine.

It is also possible to stop the goroutine manually by calling runtime.Goexit():

Image for post
Image for post

This function will run the deferred functions first, then will call the same function seen previously when a goroutine exits.

A Journey With Go

A Journey With Go Language Programming

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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