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/swagin/issues/6Diff for the fix: https://github.com/long2ice/swagin/pull/7/files
Variable name
is created at each iteration, thus Name
field is at a different memory address and code works as expected.
Your Comments :