Make sure your code passes the following tools:
go vetgofmt -sstaticcheck(viago install honnef.co/go/tools/cmd/staticcheck@latest)
See our IDE/Editor setup doc for ways to doing that automatically.
Generated code (e.g. code generated by thrift compiler) are exempted from this rule.
Group your imports into the following 3 groups, in that order, separated by blank lines:
- Standard library packages
- Third-party packages
(non-stdlib packages without
github.com/reddit/baseplate.goprefix) - Packages from the same module
(packages with
github.com/reddit/baseplate.goprefix)
Example:
import (
"time"
"github.com/apache/thrift/lib/go/thrift"
"github.com/reddit/baseplate.go/log"
)When an imported package name is different from what is implied by the final element(s) of the import path, rename the import it to make it explicit.
Example:
import (
jwt "gopkg.in/dgrijalva/jwt-go.v3"
opentracing "github.com/opentracing/opentracing-go"
)The implied package name of all of the following is still "foo", and thus they do not need to be renamed:
.../foo.v1.../foo/v1.../foo-go.../foo.go
Most import tools already understand these conventions.
When putting all args to a function signature/call to a single line makes the line too long, Use one-per-line style with closing parenthesis on the next line. Please note that in function signatures one-per-line means one group per line instead of one arg per line.
Example:
func foo (
arg1, arg2 int,
arg3 string,
arg4 func(),
) error {
// Function body
return nil
}
foo(
1,
2,
"string",
func() {
// Function body
},
)When writing slice/map literals in one-per-line style, also make sure to put the closing curly bracket on the next line.
Example:
slice := []int{
1,
2,
3,
}
myMap := map[int]string{
1: "one",
2: "two",
}When using slice literal/args as key-value map, use two-per-line style to make sure that we always have them in pair.
Example:
log.Errorw(
"Something went wrong!",
"err", err,
"endpoint", "myEndpoint",
)Sometimes two consecutive lines could be on the same indentation level but not
the same logical level.
This usually happens when a long if condition is broke into multiple lines.
In such cases,
please add a blank line between them to highlight the change of logical level.
Example:
if condition1 && condition2 &&
condition3 && condition4 {
// do something, note the blank line before this line.
foo()
}For things not covered above, use your best judgement and follow industry best practises. Some recommended resources are: