Image for post
Image for post
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

Panics in Go are triggered when the program cannot handle an error properly, such as invalid memory access. It can also be triggered by the developer if the error is unexpected and there is no other way to deal with it. Understanding the process of recovery or termination can be useful to understand the consequences of a panicking program.

Multiple Frames

The classic example for a panic and its recover function is well documented, including by the Go blog in “Defer, Panic, and Recover.” Let’s focus on a different example where a panic involves multiple frames of deferred functions. …


Image for post
Image for post
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

A goroutine leak can easily be detected via an APM that monitors the number of live goroutines. Here is an example from NewRelic of a graph that monitors the goroutines:

Image for post
Image for post
https://docs.newrelic.com/docs/agents/go-agent/features/go-runtime-page-troubleshoot-performance-problems

A leak would lead to a continuous increase of this number until the server crashes. However, there are ways to prevent leaks even before the code is deployed.

Leak detection

The Go team at Uber, which is very active on Github, made their goroutine leak detector, a tool that aims to be integrated with the unit tests. This package actually monitors the goroutines that leak the current piece of code tested. …


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.

The Go standard library dedicates a thread to watch after your application and help with bottlenecks your program could face. This thread, called sysmon, stands for system monitor, is not linked to any P in the G,M,P model, meaning it is not taken into account in the scheduler and therefore is always running. Here is an updated diagram with this special thread:

Image for post
Image for post

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

Also, you will not see this thread in the traces via the Go tool trace. …


Image for post
Image for post
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

Error management in Go is always prone to debate and a recurrent topic in the annual survey about the biggest challenges developers are facing when using Go. However, when it comes to dealing with errors in a concurrent environment or combining multiple errors for the same goroutine, Go provides great packages that make the management of multiple errors easy. Let’s look at how to combine several errors generated by a single goroutine.

One goroutine, multiple errors

Combining multiple errors into one can be use quite useful when you are working on a code that has a retrial policy, for instance. …


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.

Go provides built-in functions to help the developers working with channels, slices, or maps. Some of them have a proper internal implementation, like make(), and some do not have any implementation and are managed by the compiler. Let’s analyze some built-in functions to understand how Go handles them.

Slices

Go has, sometimes, the ability to replace a function call done at the runtime by its result if it can be known in advance. Let’s see an example with the slices:

func main() {
s := make([]int, 0, 6)
s = append(s, 12)
s = append(s, 34)

l := len(s)
println("the length is ", l)

c := cap(s)
println("the capacity is ", c)…


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.

The escape analysis one of the phases of the Go compiler. It analyses the source code and determines what variables should be allocated on the stack and which ones should escape to the heap.

Static analysis

Go statically defines what should be heap or stack-allocated during the compilation phase. This analysis is available via the flag -gcflags="-m" when compiling and/or running your code thanks to go run or go build. Here is a simple example:

func main() {
num := getRandom()
println(*num)
}

//go:noinline
func getRandom() *int {
tmp := rand.Intn(100)

return &tmp
}

Running the escape analysis shows us tmp escapes to the…


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.

Go provides memory synchronization mechanisms such as channel or mutex that help to solve different issues. In the case of shared memory, mutex protects the memory against data races. However, although two mutexes exist, Go also provides atomic memory primitives via the atomic package to improve performance. Let’s first go back to the data races before diving into the solutions.

Data Race

A data race can occur when two or more goroutines access the same memory location concurrently, and at least one of them is writing. …


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.

A deadlock is a state that happens when a goroutine is blocked without any possibility to get unblocked. Go provides a deadlock detector that helps developers not get stuck in this kind of situation.

Detection

Let’s start with an example that creates this situation:

Image for post
Image for post

The main goroutine is blocked on the channel and waiting for another one to push data into the channel. However, no other goroutine is running, and it cannot be unblocked. This situation triggers the deadlock error:

Image for post
Image for post

The deadlock detector bases its analysis of the threads created by the application. There is a deadlock situation if the number of threads created and active is higher than the threads waiting for work. …


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.

Timers are useful in executing code at some point in the future. Go internally manages the created timers along with planning their execution. The latter one can be a bit tricky since the Go scheduler is a cooperative scheduler, meaning a goroutine has to stop by itself (blocking on a channel, system calls, etc.) or paused by the scheduler at some scheduling point.

For more information about the preemption, I suggest you read my article “Go: Goroutine and Preemption.”

Cycle of Life

Here is a basic example of a timer:

Image for post
Image for post

When a timer is created, it is saved on an internal list of timers linked to the current P. Here is a representation with the previous…


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.

The relocation is a stage during the linking process that assigns proper addresses to each external symbol. Since the packages are compiled separately, they have no idea where the actual functions or variables from other packages are. Let’s start with a trivial example where relocation is needed.

Compilation

The following program involves two different packages: main and fmt.

Image for post
Image for post

Building this program will first involve the compiler that compiles each package separately:

Image for post
Image for post

With those intermediate files, we can look at them to see temporary instruction addresses thanks to the command go tool compile -S -l main.go: …

About

Vincent Blanchon

French Gopher in Dubai

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