Skip to main content

Top 10 Go Principles

A quick reference for how Go encourages you to structure code.

1. The entry point: explicit execution​

Go does not allow "floating" code. Everything must be contained within a block. This keeps you from being surprised by side effects when you open a file.

  • Rule: If it is not in a func, it is not happening.
  • Blueprint: func main() is the master toggle for your program.

2. The file system: packages as boundaries​

The folder structure is the API boundary. You organize to define "who knows what."

  • Rule: A package should do one thing (e.g., store handles data, api handles web).
  • Directional flow: api → store (legal) | store → api (circular dependency error).

3. Data-centric logic: data owns behavior​

Instead of creating "manager" classes, Go attaches functions directly to the data they modify.

  • Method: func (p Product) Calculate() attaches the logic to the Product struct.
  • Mental model: The data carries its own toolbox.

4. The "valve": intentional mutation​

Go makes you choose if a function can "write" to data or just "read" it.

  • Value receiver (p Product): A copy. Safe, no side effects.
  • Pointer receiver (p *Product): The original. Allows modification.
  • Rule: Use * when you need to change state; otherwise keep it read-only.

5. Flow control: errors as values​

Go treats errors like any other piece of data. There is no hidden crash (exception). You must decide what to do immediately.

  • Pattern: result, err := DoWork()
  • Mental model: Every risky door returns both the prize and a status report.

6. Semantic clarity: domain types​

Do not use string for everything. If a string is specifically a UserID, name it that.

  • Rule: type UserID string prevents you from passing a Password into a function expecting an ID.

7. Decoupling: consumer-defined interfaces​

In other languages, a class says "I implement this interface." In Go, the caller defines the interface.

  • Rule: If it walks and quacks like a duck, it is a duck. Match the signature, no declaration required.

8. Structural building: composition​

Go avoids the family tree (inheritance) in favor of Lego bricks (composition).

  • Pattern: To give a service logging, embed a Logger.
  • Result: Flatter structures and less spaghetti logic.

9. Responsibilities: thin main, fat packages​

The main.go file is the wiring closet. It connects the database to the server and gets out of the way.

  • Rule: Business logic lives in packages; initialization lives in main.

10. Communication: channels and concurrency​

Go's motto: "Do not communicate by sharing memory; instead, share memory by communicating."

  • Tool: Channels (chan) act as conveyor belts between goroutines.
  • Rule: Use channels to orchestrate timing rather than guessing with time.Sleep.