Go Booby Traps Part 2

intercloud team.Jun 09, 2022

Go programming language is easy to learn, but there are some tricky traps. This article series is trying to show these booby traps so that you avoid them.

Trap#1

Let’s say we want to start goroutines to print integers from 0 to 9. We could write (code on the Playground):

But if we run this program we print:

This is not what we expected! Why is this code broken? How to fix it?

Explanation

This code doesn’t work because goroutines take some time to start and when they run, the loop has already reached its maximum value of 10. Thus all goroutines print this value. Sometimes goroutines print other values, but this code doesn’t work anyway.

The best way to fix this code is to pass value for i to the goroutine function (code on the Playground):

This code works because value for i is passed by value to the goroutine and is copied to start the go routine:

You may notice that this code doesn’t print values in ascending order… this is because goroutines take some time to start and this time is not exactly the same for all go routines.

Trap#2

Let’s say we have User structures and we want to make a list of names. As there may be a lot of them, we would like to build a slice of pointers to these names. We could write following code (on the Playground) :

But when we run this code, we get:

Why is this code broken? How would you fix it?

Explanation

When we iterate on users with range, Go reuses the same variable for user and thus it is at the same memory address. So at each iteration, the address of Name field of user is identical and pointer has the same value. Thus the name in the whole slice points to the Name value in the last iteration.

To fix this, we can create a variable for the name as follows (on the Playground) :

Variable name is created at each iteration, thus Name field is at a different memory address and code works as expected.

Conclusion

This example is taken from a real bug :

Issue description: https://github.com/long2ice/sw...
Diff for the fix: https://github.com/long2ice/sw...
Variable name is created at each iteration, thus Name field is at a different memory address and code works as expected.

InterCloud

InterCloud’s end-to-end global connectivity platform eliminates the complexity in deploying the cloud, giving businesses full control over the security, sovereignty and performance of their critical data traffic with complete peace of mind.

Working with organisations to help them transform global connectivity, reduce network complexity and accelerate growth and innovation, InterCloud is a trusted advisor to some of the world's leading brands when it comes to leveraging the cloud for future success

With offices across Europe, the company's platform is underpinned by its team of cloud experts who guide customers to implement effective strategies to leverage the power of the cloud across their organisation – making global connectivity a driver for business performance .

www.intercloud.com

Unchain the cloud, unleash your potential