Do you make these Go coding mistakes?
This collection of Go gotchas and pitfalls will 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.
-
Assignment to entry in nil map
You have to initialize a map using the make function (or a map literal) before you can add any elements.
-
Invalid memory address or nil pointer dereference
An uninitialized pointer is nil, and you can’t follow the nil pointer. If x is nil, an attempt to evaluate *x will cause a run-time panic.
-
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.
-
Arrays in Go are values: when you pass an array to a function it gets a copy of the original array data. If you want a function to update its elements, use a slice that refers to the array.
-
An identifier declared in a block may be redeclared in an inner block. The new variable shadows the original throughout the scope of the inner block.
-
In a multi-line slice, array or map literal, every line must end with a comma. As a result, you can add and remove lines without modifying the surrounding code.
-
Go strings are read-only byte slices (with a few extra properties). To update string data, consider using a rune slice instead.
-
Characters (rune literals) are integer values used to identify Unicode code points. You can turn a code point into a string with a conversion.
-
The Trim functions strip all Unicode code points contained in a cutset. To strip a trailing string, use TrimSuffix.
-
Copy copies the minimum number of elements in the destination and source slices. To make a full copy, you must allocate a big enough destination slice.
-
Why doesn’t append work every time? [scary bug]
If there is enough capacity, append reuses the underlying array.
-
An untyped integer constant is converted to an int when the type can’t be inferred from the context.
-
Unexpected ++, expecting expression
In Go increment and decrement operations can’t be used as expressions, only as statements. Only postfix notation is available.
-
In Go the multiplication, division, and remainder operators have the same precedence.
-
The circumflex (^) denotes bitwise XOR in Go.
-
An integer overflow occurs when an arithmetic operation tries to create a value that is outside the range that can be represented.
-
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.
-
There is no mixing of numeric types in Go.
-
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.
-
Only the the exported fields of a Go struct will be present in the JSON output.
-
Most of the functions in the regexp package do substring matching.
-
An interface value is nil only if the concrete value and dynamic type are both nil.
This Concurrent programming tutorial includes several gotchas and pitfalls related to concurrent programming in Go.