Golang

This section contains development guidelines about writing code in Go.

Coding guidelines

General style

A1. Go projects should follow the Standard Go Project Layoutarrow-up-right. To this end you may use the Go Project Templatearrow-up-right.

A2. Code should be formatted according to the rules of go fmtarrow-up-right and go vetarrow-up-right. Example or a working Make target used in several projects, that allows to format a Go module:

test_fmt:
	@echo Checking correct formatting of files
	@{ \
		files=$$( go fmt ./... ); \
		if [ -n "$$files" ]; then \
		echo "Files not properly formatted: $$files"; \
		exit 1; \
		fi; \
		if ! go vet ./...; then \
		exit 1; \
		fi \
	}

A3. Code should adhere to the golintarrow-up-right rules. Example of a working Make target used in several projects, that allows to check a Go module linting:

test_lint:
	@echo Checking linting of files
	@{ \
		GO111MODULE=off go get -u golang.org/x/lint/golint; \
		el=$(EXCLUDE_LINT); \
		lintfiles=$$( golint ./... | egrep -v "$$el" ); \
		if [ -n "$$lintfiles" ]; then \
		echo "Lint errors:"; \
		echo "$$lintfiles"; \
		exit 1; \
		fi \
	}

A4. To set up local variables in if and switch control structures, you should use whenever applicable the initialisation statement construct.

A5. To loop over an array, slice, string or map, or reading from a channel, you should use the range clause.

A6. To generate cryptographic keys, you must not use math/rand. Use crypto/rand's Reader instead, and print to hexadecimal or base64 if you need text. crypto/rand should always be used, even in tests or in contexts that does not have high security requirements, to avoid the introduction of vulnerabilities in later development stages stemming from incautious copy-paste operations.

A7. When declaring an empty slice, prefer this notation:

Variables, functions, packages and modules

B1. MixedCaps should be used to write multiword names.

B2. Words in names that are initialisms or acronyms (e.g. "URL" or "NATO") should have a consistent case. For example, "URL" should appear as "URL" or "url" (as in "urlPony", or "URLPony"), never as "Url". This rule also applies to "ID" when it is short for "identifier", so you should write "appID" instead of "appId".

B3. Named result parameters should be used only in short functions.

B4. The defer statement should be used to release resources used by functions (e.g. I/O operations).

B5. Security credentials, tracing information, deadlines, and cancellation signals should be passed across functions as values of the context.Context type.

B6. Functions using a Context should accept it as first parameter.

B7. A function that is never request-specific may use context.Background() instead of Context.

B8. Functions should always return an error or boolean to indicate whether its other return values are valid or not, and not rely on special or magic return values to indicate error.

B9. Packages should have single-word names, and they must match the base name of their source directory.

circle-info

As an example, the package insrc/encoding/base64 should have name base64(and be imported asencoding/base64).

B10. Modules should be defined by using go.modarrow-up-right.

Errors and log

C1. Functions should always return an error or boolean to indicate wether its other return values are valid or not, and not rely on special or magic return values to indicate error. For severe errors which cause the application to crash, the panic function may be used instead.

C2. The panic function should be used with caution and not for normal error handling. If used, it should be properly documented so that it has the chance to be caught.

C3. The log.Fatal function should not be used.

C4. Error and log strings should not be capitalised nor end with punctuation.

Testing

D1. Testing of Go projects should be implemented by using the built-in testing packagearrow-up-right provided by the Go's standard library, and run by using the test commandarrow-up-right. Note that you must implement your tests in a file whose name ends in _test.go, and you must put it in the same package of the file it tests (not in a separate xxx_test package).

D2. If your tests depend on external components (e.g. a database, network, etc.), the calls to these dependencies should be properly separated from the main code by an interface, and the interfaces mocked to simulate the external component during tests.

D3. The tests should be easily executable and automated. Example or a working Make target used in several projects, that allows to execute tests:

Versioning

E1. Go modules must comply to Semantic Import Versioningarrow-up-right in order to be importable. Note that this is particularly important for versions >= v2, as this requires changes in the go.mod and source files (see point E2).

E2. Before releasing a new version, follow the guide on how to prepare new releasesarrow-up-right.

Useful tools

References

Last updated

Was this helpful?