10 Common Go Mistakes That Can Sabotage Your Code

This article enumerates ten frequent Go programming errors—from unknown enum handling and benchmark mis‑optimizations to pointer misuse, slice initialization, context pitfalls, and error‑handling practices—explaining why they occur, showing reproducible code examples, and offering concrete fixes to write more reliable Go code.

System Architect Go
System Architect Go
System Architect Go
10 Common Go Mistakes That Can Sabotage Your Code

1. Unknown Enum Values

When an enum type is used in a JSON request, the zero value (often 0) is decoded as the first constant, which can misrepresent an "unknown" state. The article shows a type Status uint32 with constants StatusOpen, StatusClosed, StatusUnknown. If the JSON omits the Status field, the decoder sets it to StatusOpen, breaking business semantics. The recommended practice is to make the unknown value the zero constant, e.g., declare StatusUnknown first.

2. Benchmark Pitfalls

Benchmarks can be skewed when the compiler inlines a leaf function without side effects, removing the call entirely. The article demonstrates a clear function that is inlined and eliminated, producing inaccurate results. The fix is to prevent the compiler from discarding the call by assigning the result to a global variable, ensuring the benchmark measures real work.

3. Pointer vs. Value Passing

Passing by value creates a copy, while passing a pointer copies only the address. For small data, copying is often faster than dereferencing a pointer. The article explains Go's escape analysis: values that escape a goroutine are moved to the heap, while stack‑allocated values are reclaimed without GC overhead. It also shows when a pointer does not escape because the caller and callee run in the same goroutine.

4. Breaking Out of for / switch / select

Using break inside a switch or select only exits that construct, not the surrounding for loop. To break the outer loop, a labeled break (e.g.,

loop:
for { … break loop }

) is required.

5. Error Management

The standard library provides only errors.New, making it hard to add context or hierarchy. The article recommends the github.com/pkg/errors package, showing how to wrap errors with errors.Wrapf and propagate them, and how to inspect the root cause with errors.Cause for retry logic.

6. Slice Initialization

Creating a slice with make([]Bar, 0) allocates a zero‑length backing array that will grow as elements are appended, causing repeated allocations. When the final length is known, pre‑allocate the exact size to avoid unnecessary growth and improve performance.

7. Context Management

context.Context

carries deadlines, cancellation signals, and key/value pairs. The article clarifies how to compose contexts, share them across goroutines, and avoid unintended cancellation cascades by using parent‑child contexts appropriately.

8. Forgetting -race in Tests

Running tests without the -race flag misses data‑race detection. Enabling it is essential for reliable concurrent code.

9. Using Filenames Directly as Input

Hard‑coding a filename inside a function makes testing difficult. The article suggests accepting an io.Reader (or bufio.Reader) instead, allowing callers to supply files, HTTP bodies, or in‑memory strings, which simplifies unit testing.

10. Goroutine Loop Variable Capture

When launching goroutines inside a for range loop, the loop variable is shared, leading to all goroutines printing the final value. The fix is to pass the variable as a parameter to the closure or create a new variable inside the loop scope.

For further reading, see the following resources:

https://dave.cheney.net/high-performance-go-workshop/dotgo-paris.html?#watch_out_for_compiler_optimisations

https://www.ardanlabs.com/blog/2017/05/language-mechanics-on-stacks-and-pointers.html

https://www.youtube.com/watch?v=ZMZpH4yT7M0&feature=youtu.be

https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully

http://p.agnihotry.com/post/understanding_the_context_package_in_golang/index.html

https://medium.com/@val_deleplace/does-the-race-detector-catch-all-data-races-1afed51d57fb

https://github.com/golang/go/wiki/CommonMistakes

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceGoBenchmarkError Handlingpointerscontextcommon mistakes
System Architect Go
Written by

System Architect Go

Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.