Go: g0, Special Goroutine

Vincent Blanchon
Jan 3, 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.13.

All the goroutines created in Go are under the management of an internal scheduler. The Go scheduler tries to give running time to all goroutines and keep all CPU busy with running goroutines when the current ones are blocked or terminated. It actually runs as a special goroutine.

Scheduling goroutine

Go limits the number of OS thread running thanks to GOMAXPROCS variable simultaneously. That means Go has to schedule and manage goroutines on each of the running threads. This role is delegated to a special goroutine, called g0, that is the first goroutine created for each OS thread:

Image for post
Image for post

Then, it will schedule ready goroutines to run on the threads.

For more information about the P, M, G model, I suggest you read my article “Go: Goroutine, OS Thread and CPU Management.”

To better understand how scheduling works on g0, let’s review the usage of the channels. Here is when a goroutine blocks on sending on channels:

When blocking on channels, the current goroutine will be parked, i.e., be in waiting mode and not been pushed in any goroutines queues:

Image for post
Image for post

Then, g0 replaces the goroutine and does on round one scheduling:

Image for post
Image for post

The local queue has the priority during the scheduling, and the goroutine #2 will now run:

Image for post
Image for post

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

The goroutine #7 will get unblocked as soon as a receiver comes with reading the channel:

The goroutine receiving the message will switch to g0 and unlock the parked goroutine by putting it on the local queue:

Image for post
Image for post

Although the special goroutine is managing the scheduling, it is not its only job, it does much more.


Contrary to the regular goroutines, g0 has a fix and larger stack. This allows Go to perform operations where a bigger stack is needed, and when it is preferable for the stack not to grow. Among the responsibilities of g0, we can list:

  • Goroutine creation. When calling go func(){ ... }() or go myFunction(), Go will delegate the function creation to g0 before putting it on the local queue:
Image for post
Image for post

Newly created goroutines run in priority and are placed at the top of the local queue.

For more information about the prioritization of the goroutines, I suggest you read my article “Go: Concurrency & Scheduler Affinity.”

  • Defer functions allocations.
  • Garbage collector operations, such as stopping the world, scanning the stack of the goroutines, and some of the marking and sweeping operations.
  • Stack growth. When needed, Go increases the size of the goroutines. This operation is done by g0 in the prolog functions.

Involved in many other operations (large allocations, cgo, etc.), this special goroutine g0 makes our program more efficient managing operations with a need of larger stack to keep our program more efficient with low memory print.

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