Go gotcha: newbie or ninja?
27 sneaky traps and corner cases
This collection of gotchas and pitfalls in Go is intended to help you find and fix similar problems in your own code.
Some of the puzzles are pretty easy. To solve all 27, you have to be a ninja.
Table of contents
Assignment to entry in nil map
You have to initialize the map before you can add any elements.
Nil pointer dereference
An uninitialized pointer is nil, and you can't follow the nil pointer.
Multiple-value in single-value context
When a function returns multiple values, you must take care of each one. You can use the blank identifier (underscore) to ignore unwanted return values.
Array won’t change
Arrays in Go are values: when you pass an array to a function it gets a copy of the original array data.
An identifier declared in a block may be redeclared in an inner block.
In a multi-line slice, array or map literal, every line must end with a comma.
String won’t change
Go strings are read-only byte slices (with a few extra properties).
Adding one character at a time
Characters (rune literals) are integer values used to identify Unicode code points.
What happened to ABBA?
The Trim functions strip all Unicode code points contained in a cutset.
Where is my copy?
Copy copies the minimum number of elements in the destination and source slices.
Why doesn’t append work every time?
If there is enough capacity, append reuses the underlying array.
Constant overflows int
An untyped integer constant is converted to an int when the type can't be inferred from the context.
In Go increment and decrement are statements written with postfix notation.
Does not compute
The multiplication, division, and remainder operators have the same precedence.
Go and Pythagoras
The circumflex (^) denotes bitwise XOR in Go.
No end in sight
An integer overflow occurs when an arithmetic operation tries to create a value that is outside the range that can be represented.
Numbers that start with zero
Octal literals start with 0, hexadecimal with 0x, and decimal literals never start with zero.
The remainder operator can give negative answers if the dividend is negative.
Time is not a number
There is no mixing of numeric types in Go.
Index out of range
Arrays, slices and strings are indexed starting from zero.
Unexpected values in range loop
The range loop generates two values: first the index, then the data.
Can’t change entries in range loop
The range loop uses a local variable to store iteration values.
Iteration variable doesn’t see change in range loop
The range expression is evaluated once before beginning the loop.
Iteration variables and closures
A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.
No JSON in sight
Only the the exported fields of a Go struct will be present in the JSON output.
Is "three" a digit?
Most of the functions in the regexp package do substring matching.
Nil is not nil
An interface value is nil only if the concrete value and dynamic type are both nil.
The Concurrent programming tutorial covers the fundamentals of concurrent programming with examples in Go.
Share this page: