by The Pragmatic Programmer
Complexity turns reliable software in unreliable software. Complexity is what kills software projects. Therefore simplicity is the highest goal of Go.
Programs must be written for people to read, and only incidentally for machines to execute. — Hal Abelson and Gerald Sussman
all software, not just Go programs, is written by humans to be read by other humans. The fact that software is also consumed by machines is secondary.
Readability is key to being able to understand what the program is doing. If you can’t understand what a program is doing, how can you hope to maintain it? If software cannot be maintained, then it will be rewritten;
Go programmers realise that code is written to be read and so place the act of reading code above the act of writing it. Go goes so far as to enforce, via tooling and custom, that all code be formatted in a specific style. This removes the friction of learning a project specific dialect and helps spot mistakes because they just look incorrect.
Good naming is like a good joke. If you have to explain it, it’s not funny. — Dave Cheney
Good names have a high signal to noise ratio.
A good name should describe the application of a variable or constant, not their contents.
The greater the distance between a name’s declaration and its uses, the longer the name should be. — Andrew Gerrand [] From this we can draw some guidelines: Short variable names work well when the distance between their declaration and last use is short. Long variable names need to justify themselves; the longer they are the more value they need to provide. Lengthy bureaucratic names carry a low amount of signal compared to their weight on the page. Don’t include the name of your type in the name of your variable. Constants should describe the value they hold, not how that value is used.
Use blank lines to break up the flow of a function in the same way you use paragraphs to break up the flow of a document.
You shouldn’t name your variables after their types for the same reason you don’t name your pets "dog" and "cat".
The reader should be able to understand the use of a name when they encounter it for the first time. When they encounter a common name, they should be able to assume it has not changed meanings since the last time they saw it.
When declaring and initialising the variable at the same time, that is to say we’re not letting the variable be implicitly initialised to its zero value, I recommend using the short variable declaration form. This makes it clear to the reader that the variable on the left hand side of the := is being deliberately initialised.
Changing styles in the middle of a file is jarring. Uniformity, even if its not your preferred approach, is more valuable for maintenance than your personal preference.
If you want to do a renaming across a code-base, do not mix this into another change. If someone is using git bisect they don’t want to wade through thousands of lines of renaming to find the code you changed as well.
Functions should do one thing only. If you find yourself commenting a piece of code because it is unrelated to the rest of the function, consider extracting it into a function of its own.
Each Go package is in effect it’s own small Go program. Just as the implementation of a function or method is unimportant to the caller, the implementation of the functions, methods and types that comprise your package’s public API—its behaviour—is unimportant for the caller.
Name your package for what it provides, not what it contains.
[A little] duplication is far cheaper than the wrong abstraction. — Sandy Metz
Rather than the successful path nesting deeper and deeper to the right, Go code is written in a style where the success path continues down the screen as the function progresses. My friend Mat Ryer calls this practice 'line of sight' coding. [] This is achieved by using guard clauses; conditional blocks with assert preconditions upon entering a function.
The key to writing maintainable programs is that they should be loosely coupled—a change to one package should have a low probability of affecting another package that does not directly depend on the first. There are two excellent ways to achieve loose coupling in Go Use interfaces to describe the behaviour your functions or methods require. Avoid the use of global state.