Go Code Smells

Common code smells in Go and how to fix them.


Ignoring Errors

1// ❌ Bad
2result, _ := doSomething()
3
4// ✅ Good
5result, err := doSomething()
6if err != nil {
7    return fmt.Errorf("failed: %w", err)
8}

Not Using defer

 1// ❌ Bad
 2file, err := os.Open("file.txt")
 3if err != nil {
 4    return err
 5}
 6data, err := io.ReadAll(file)
 7file.Close()
 8return data, err
 9
10// ✅ Good
11file, err := os.Open("file.txt")
12if err != nil {
13    return err
14}
15defer file.Close()
16data, err := io.ReadAll(file)
17return data, err

Goroutine Leaks

 1// ❌ Bad: Goroutine never stops
 2func process() {
 3    ch := make(chan int)
 4    go func() {
 5        for {
 6            select {
 7            case v := <-ch:
 8                process(v)
 9            }
10        }
11    }()
12}
13
14// ✅ Good: Use context
15func process(ctx context.Context) {
16    ch := make(chan int)
17    go func() {
18        for {
19            select {
20            case v := <-ch:
21                process(v)
22            case <-ctx.Done():
23                return
24            }
25        }
26    }()
27}

Pointer to Loop Variable

 1// ❌ Bad
 2var results []*Item
 3for _, item := range items {
 4    results = append(results, &item)
 5}
 6
 7// ✅ Good
 8var results []*Item
 9for i := range items {
10    results = append(results, &items[i])
11}

Naked Returns

 1// ❌ Bad
 2func calculate(x, y int) (result int, err error) {
 3    // ... 50 lines ...
 4    result = x + y
 5    return
 6}
 7
 8// ✅ Good
 9func calculate(x, y int) (int, error) {
10    // ... code ...
11    result := x + y
12    return result, nil
13}

Related Snippets