mirror of
https://github.com/teivah/100-go-mistakes.git
synced 2026-06-21 08:57:07 +08:00
166 lines
6 KiB
Markdown
166 lines
6 KiB
Markdown
# 100 Go Mistakes and How to Avoid Them
|
|
|
|
Source code of [100 Go Mistakes and How to Avoid Them](https://www.manning.com/books/100-go-mistakes-and-how-to-avoid-them) 📖, edited by Manning.
|
|
|
|

|
|
|
|
## Table of Contents
|
|
|
|
### Chapter 1 - Introduction
|
|
|
|
### Chapter 2 - Code and Project Organization
|
|
|
|
* 1 - Unintended variable shadowing
|
|
* 2 - Writing nested code
|
|
* 3 - Misusing init functions
|
|
* 4 - Always using getters and setters
|
|
* 5 - Interface pollution
|
|
* 6 - Interface on the producer side
|
|
* 7 - Returning interfaces
|
|
* 8 - `any` says nothing
|
|
* 9 - [Being confused about when to use generics](https://teivah.medium.com/when-to-use-generics-in-go-36d49c1aeda)
|
|
* 10 - Not being aware of the possible problems with type embedding
|
|
* 11 - Not using the functional options pattern
|
|
* 12 - Project misorganization (project structure and package organization)
|
|
* 13 - Creating utility packages
|
|
* 14 - Ignoring package name collisions
|
|
* 15 - Missing code documentation
|
|
* 16 - Not using linters
|
|
|
|
### Chapter 3 - Data Types
|
|
|
|
* 17 - Creating confusion with octal literals
|
|
* 18 - Neglecting integer overflows
|
|
* 19 - Not understanding floating-points
|
|
* 20 - Not understanding slice length and capacity
|
|
* 21 - Inefficient slice initialization
|
|
* 22 - Being confused about nil vs. empty slice
|
|
* 23 - Not properly checking if a slice is empty
|
|
* 24 - Not making slice copy correctly
|
|
* 25 - Unexpected side-effects using slice append
|
|
* 26 - Slice and memory leaks
|
|
* 27 - Inefficient map initialization
|
|
* 28 - Map and memory leaks
|
|
* 29 - Comparing values incorrectly
|
|
|
|
### Chapter 4 - Control Structures
|
|
|
|
* 30 - Ignoring that elements are copied in `range` loops
|
|
* 31 - Ignoring how arguments are evaluated in `range` loops (channels and arrays)
|
|
* 32 - Ignoring the impacts of using pointer elements in `range` loops
|
|
* 33 - Making wrong assumptions during map iterations (ordering and map insert during iteration)
|
|
* 34 - Ignoring how the `break` statement work
|
|
* 35 - Using `defer` inside a loop
|
|
|
|
### Chapter 5 - Strings
|
|
|
|
* 36 - Not understanding the concept of rune
|
|
* 37 - Inaccurate string iteration
|
|
* 38 - Misusing trim functions
|
|
* 39 - Under-optimized strings concatenation
|
|
* 40 - Useless string conversion
|
|
* 41 - Substring and memory leaks
|
|
|
|
### Chapter 6 - Functions and Methods
|
|
|
|
* 42 - Not knowing which type of receiver to use
|
|
* 43 - Never using named result parameters
|
|
* 44 - Unintended side-effects with named result parameters
|
|
* 45 - Returning a nil receiver
|
|
* 46 - Using a filename as a function input
|
|
* 47 - Ignoring how defer arguments and receivers are evaluated
|
|
|
|
### Chapter 7 - Error Management
|
|
|
|
* 48 - Panicking
|
|
* 49 - Ignoring when to wrap an error
|
|
* 50 - Comparing an error type inaccurately
|
|
* 51 - Comparing an error value inaccurately
|
|
* 52 - Handling an error twice
|
|
* 53 - Not handling an error
|
|
* 54 - Not handling defer errors
|
|
|
|
### Chapter 8 - Concurrency: Foundations
|
|
|
|
* 55 - Mixing concurrency and parallelism
|
|
* 56 - Concurrency isn't always faster
|
|
* 57 - Being puzzled about when to use channels or mutexes
|
|
* 58 - Not understanding race problems (data races vs. race conditions and Go memory model)
|
|
* 59 - Not understanding the concurrency impacts of a workload type
|
|
* 60 - Misunderstanding Go contexts
|
|
|
|
### Chapter 9 - Concurrency: Practice
|
|
|
|
* 61 - Propagating an inappropriate context
|
|
* 62 - Starting a goroutine without knowing when to stop it
|
|
* 63 - Not being careful with goroutines and loop variables
|
|
* 64 - Expecting a deterministic behavior using select and channels
|
|
* 65 - Not using notification channels
|
|
* 66 - Not using nil channels
|
|
* 67 - Being puzzled about a channel size
|
|
* 68 - Forgetting about possible side-effects with string formatting (etcd and dead-lock)
|
|
* 69 - Creating data races with append
|
|
* 70 - Using mutexes inaccurately with slices and maps
|
|
* 71 - Misusing `sync.WaitGroup`
|
|
* 72 - Forgetting about `sync.Cond`
|
|
* 73 - Not using `errgroup`
|
|
* 74 - Copying a `sync` type
|
|
|
|
### Chapter 10 - Standard Library
|
|
|
|
* 75 - Providing a wrong time duration
|
|
* 76 - `time.After` and memory leak
|
|
* 77 - JSON handling common mistakes
|
|
* Unexpected behavior because of type embedding
|
|
* JSON and monotonic clock
|
|
* Map of `any`
|
|
* 78 - SQL common mistakes
|
|
* Forgetting that `sql.Open` doesn't necessarily establish connections to a DB
|
|
* Forgetting about connections pooling
|
|
* Not using prepared statements
|
|
* Mishandling null values
|
|
* Not handling rows iteration errors
|
|
* 79 - Not closing transient resources (HTTP body, `sql.Rows`, and `os.File`)
|
|
* 80 - Forgetting the return statement after replying to an HTTP request
|
|
* 81 - Using the default HTTP client and server
|
|
|
|
### Chapter 11 - Testing
|
|
|
|
* 82 - Not categorizing tests (build tags and short mode)
|
|
* 83 - Not enabling the race flag
|
|
* 84 - Not using test execution modes (parallel and shuffle)
|
|
* 85 - Not using table-driven tests
|
|
* 86 - Sleeping in unit tests
|
|
* 87 - Not dealing with the time API efficiently
|
|
* 88 - Not using testing utility packages (`httptest` and `iotest`)
|
|
* 89 - Writing inaccurate benchmarks
|
|
* Not resetting or pausing the timer
|
|
* Making wrong assumptions about micro-benchmarks
|
|
* Not being careful about compiler optimizations
|
|
* Being fooled by the observer effect
|
|
* 90 - Not exploring all the Go testing features
|
|
* Code coverage
|
|
* Testing from a different package
|
|
* Utility functions
|
|
* Setup and teardown
|
|
|
|
### Chapter 12 - Optimizations
|
|
|
|
* 91 - Not understanding CPU caches
|
|
* CPU architecture
|
|
* Cache line
|
|
* Slice of structs vs. struct of slices
|
|
* Predictability
|
|
* Cache placement policy
|
|
* 92 - Writing concurrent code leading to false sharing
|
|
* 93 - Not taking into account instruction-level parallelism
|
|
* 94 - Not being aware of data alignment
|
|
* 95 - Not understanding stack vs. heap
|
|
* 96 - Not knowing how to reduce allocations
|
|
* API change
|
|
* Compiler optimizations
|
|
* `sync.Pool`
|
|
* 97 - Not relying on inlining
|
|
* 98 - Not using Go diagnostics tooling (profiling and execution tracer)
|
|
* 99 - Not understanding how the GC works
|
|
* 100 - Not understanding the impacts of running Go inside of Docker and Kubernetes
|