Conventions and Such
Various notes on writing Go Code. Mainly taken from Effective Go and How To Write Go Code.
Other notable resources:
Files and Packages
Use snake_case
for multi-file packages. e.g., if a package has multiple files, use mypackage/another_func.go
. Function names are still camel case. Anything exported from the package is capitalized.
Formatting
- Use
gofmt
orgo fmt
whenever possible. This is one of the cool features of go — formatting is built into the language. - No semi-colons.
- Use tabs. Not spaces.
- Fewer parentheses than most other languages —
if
andfor
andswitch
etc. all don’t use parentheses. - No rules about line-length. If you want to split things onto multiple lines, you can.
- Comments and
godoc
have some special magic that plays well together. Generally speaking, add a comment to every exported function of a package; add a block comment to every package. - Functions can be called before they’re declaration (similar to JS hoisting behavior)/
Naming Conventions
CamelCase
for multi-word variable and function names- Go leans towards short names for variables and stuff. e.g.,
i
notindex
. The larger the scope and significance of a variable, the longer the name. - Package names in lower case
- Acronyms and initials - the important part is that the same case is used for the acronym, e.g.
httpResponse
orrequestHTML
are both acceptable, but NOTrequestHtml
- Any function that might panic should be prefixed with
Must
. e.g.,MustParseIntFromString
- Any interface should be a
-er
suffix. e.g.,Reader
,Writer
,Storer
, etc.
Coding Style
Generally, go tends to go towards succinct code as it’s method to achieve readability. Go made me realize that if
statements have lexical block just in the statement.
func doStuff (fName) {
if fName === "some name" {
fmt.Println("It is the file u want")
}
}
This statement has 3 scopes. The function scope, the if
statement’s declaration scope (if fName ===...
) and the if statment block body.
If a variable can be enclosed in an if
statement’s declaration that is not needed outside of this scope, then it certainly should be. For succinctness.
For example:
func doThings (fName) {
if _, err := os.Stat(fName); os.IsNotExist(err) {
fmt.Println("This file does not exist")
}
}
There’s a lot encapsulated in the scope of this if statement. It doesn’t leak outside the if statement declaration. That’s considered a good thing in go.
Organizing one file
Syntactically speaking, the order of your function and type declarations does not matter in Go. Go does not parse top-to-bottom like a scripting language or procedural style, so you don’t need to define a function “before” using it, e.g., it doesn’t need to be defined higher in the file.
In Go, the convention is to declare the entrypoint function at the top of the file, then declare the functions used in that function below.
package main
import (
"fmt"
"time"
)
// constants
const (
TIMEZONE = "America/Buenos_Aires"
LAYOUT = "3:04pm"
)
// typedefs
type SomeType struct {
///
}
// main func calls tellMeWhatTimeItIsInBuenosAires
func main() {
fmt.Println("Starting the app")
tellMeWhatTimeItIsInBuenosAires()
}
// declare BELOW main func
func tellMeWhatTimeItIsInBuenosAires() {
nowInBuenosAires := time.Now().In(TIMEZONE).Format(LAYOUT)
fmt.Println("The time in Buenos Aires is %s", nowInBuenosAires)
}
Also, similarly, put more important things near the top of the file. e.g., exported functions should be above private funcs.
Organizing many files
Generally go doesn’t care too much about how you organize your files in a project. But, there are some basic conventions:
- There should be a directory called
cmd
in the root of your project, each subdir in this directory is an application-specific use of other code and packages from the project. For example,cmd/www
would be the web-based entrypoint,cmd/cli
would be the CLI-based entrypoint, etc. - There should be a directory called
internal
in the root of your project. In here goes non-application-specific code. For example, reusable business logic would go ininternal
, which could then be used by both the cli and www entrypoints, and is unaware of if it’s handling an http request or whatever it’s doing.
Initialisms and Acronyms
Super annoying topic, but they make the convention clear in the community: casing for acronyms and initialisms should be consistent, and preferably upper case. Lower case is okay as long as it’s consistent and not camelized.
For example, URLParser
, urlParser
, parseURL
are all acceptable, while parseUrl
, UrlParser
are both unnacceptable.