Open12

100 Go Common Mistakes

IchiIchi

Interface Pollution (#5)

The main use cases for us to use interfaces in Go.

  1. Common behavior
  2. Decoupling
  3. Restricting behavior (counter intuitive)

Abstractions should be discovered, not created.
--> We shouldn't start creating abstractions in our code if there is no immediate reason to do so.

Don't design with interfaces, discover them.
If it's unclear how an interface makes the code better, we should probably consider removing it to make our code simpler.

IchiIchi

Interface on the producer side (#6)

Interfaces are satisfied implicitly in Go(that's why this mechanism is called duck typing),which tends to be a gamechanger compared to other languages with an explicit implementation.

It's better that it's up to client side to decide whether it needs some form of abstraction and then determine the best abstraction level for its needs.

IchiIchi

Being confused about when to use generics (#9)

For instance, functions working with slices, maps, and channels of any type.
A function to merge to channels would work with any channel type.
Hence, we could use type parameters to factor out the channel type:

func merge[T any](ch1, ch2 <-chan T) <- chan T {
    // ...
}
IchiIchi

Project misorganization (project structure and package organization) (#12)

To help clients understand a Go project, we should name our packages after what they provice, not what they contain.
A package name should be short, concise, expressive, and, by convention, a single lowercase word.

In 2023, the Go team has published an official guideline for organizing / structuring a Go project: https://go.dev/doc/modules/layout

IchiIchi

Missing code documentation (#15)

Documentation is an important aspect of coding.

First, every exported element must be documented, whether it's a structure, an interface, a function, or something else, if it's exported, it must be documented.
--> It was suprising for me because many exported components on my team's Go project don't have documentation..

When it comes to documenting a variable or a constant, we might be interested in conveying two aspects.

  1. purpose: should live as code documentation to be useful for external clients
  2. its content: shouldn't necessarily be public

To help clients and maintainers understand a package's scope, we should also document each package.
The convention is to start the comment with // Package followed by the package name.
The first line of a package comment should be concise. That's because it will appear in the package.
Then, we can provide all the information we need in the following lines.

IchiIchi

Creating confution with octal literals (#17)

  • Binary - Uses a 0b or 0B prefix (for example, 0b100 is equal to 4 in base 10)
  • Octal - Uses an 0o or 0O prefix (for example, 0o10 is equal to 8 in base 10)
  • Hexadecimal - Uses an 0x or 0X prefix (for example 0xF is equal to 15 in base 10)
  • Imaginary - Uses an i suffix (for example, 3i)
IchiIchi

Not understanding slice length and capacity (#20)

IchiIchi

Not properly checking if a slice is empty (#23)

Slice's length checking works regardless of whether the slice is nil or empty.
This principle is the same with maps.

IchiIchi

Not making slice copies correctly (#24)

    src := []int{0, 1, 2}
    var dst []int
    copy(dst, src)
    fmt.Println(dst) // []
IchiIchi

Ingnoring how the break statement works (#34)

One essential rule to keep in mind is that a break statement terminates the innermost for, which or select statement. In the previous example, it terminates only the switch statement.

IchiIchi

Not understainding the concurrency impact of a workload type(#59)

In programming, the execution time of workload is limited by one of the following:

  • The Speed of the CPU
    • For example, runnning a merge sort algorithm. This kind of workload is called CPU-bound.
  • The Speed of I/O
    • For example, making a REST call or a database query.The workload is called I/O-bound.
  • The Amount of Available Memory
    • The workload is called memory-bound.
IchiIchi

Creating data reces with append(#69)

We should remember that using append on a shared slice in concurrent applications can lead to a data race. Hence, it should be avoided.