RuleDescriptionExampleKPI
S1001-Replace for loop with call to copyUse copy() for copying elements from one slice to another.

//non-compliant code

for i, x := range src {
dst[i] = x
}

//compliant code

copy(dst, src)
Functionality, Efficiencylow
S1002-Omit comparison with boolean constantOmit comparison with boolean constant//non-compliant code

if x == true {}

//compliant code


if x {}
Functionalitylow
S1005-Drop unnecessary use of the blank identifierIn many cases, assigning to the blank identifier is unnecessary.//non-compliant code

for _ = range s {}
x, _ = someMap[key]
_ = <-ch


//compliant code

for range s{}
x = someMap[key]
<-ch
Functionalitylow
S1006-Use for { ... } for infinite loopsFor infinite loops, using for { ... } is the most idiomatic choice.Functionalitylow
S1012-Replace time.Now().Sub(x) with time.Since(x)Replace time.Now().Sub(x) with time.Since(x)//non-compliant code

time.Now().Sub(x)


//compliant code

time.Since(x)
Functionalitylow
S1020-Omit redundant nil check in type assertionOmit redundant nil check in type assertion//non-compliant code

if _, ok := i.(T); ok && i != nil {}


//compliant code

if _, ok := i.(T); ok {}

Functionalitylow
S1021-Merge variable declaration and assignmentMerge variable declaration and assignment//non-compliant code

var x uint
x = 1


//compliant code

var x uint = 1

Functionalitylow
S1031-Omit redundant nil check around loopOmit redundant nil check around loopFunctionalitylow
S1032-Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)The sort.Ints, sort.Float64s and sort.Strings functions are easier to read than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x)) and sort.Sort(sort.StringSlice(x)).//non-compliant code

sort.Sort(sort.StringSlice(x))



//compliant code

sort.Strings(x)

Functionalitylow
S1033-Unnecessary guard around call to deleteCalling delete on a nil map is a no-op.Functionalitylow
S1034-Use result of type assertion to simplify casesUse result of type assertion to simplify casesMaintainabilitylow
S1036-Unnecessary guard around map accessWhen accessing a map key that doesn't exist yet, one receives a zero value. Often, the zero value is a suitable value, for example when using append or doing integer math.//non-compliant code

if _, ok := m["foo"]; ok {
m["foo"] = append(m["foo"], "bar")
} else {
m["foo"] = []string{"bar"}
}



//compliant code

m["foo"] = append(m["foo"], "bar")

Functionalitylow
S1038-Unnecessarily complex way of printing formatted stringInstead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).Functionalitylow
S1039-Unnecessary use of fmt.SprintCalling fmt.Sprint with a single string argument is unnecessary and identical to using the string directly.Functionalitylow
SA1018-strings.Replace called with n == 0, which does nothingWith n == 0, zero instances will be replaced. To replace all instances, use a negative number, or use strings.ReplaceAll.Funtionalitylow
SA4000-Boolean expression has identical expressions on both sidesBoolean expression has identical expressions on both sidesFunctionalitylow
SA4001-&*x gets simplified to x, it does not copy x&*x gets simplified to x, it does not copy xFunctionalitylow
SA4003-Comparing unsigned values against negative values is pointlessComparing unsigned values against negative values is pointlessFunctionalitylow
SA4013-Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.Functionalitylow
SA4014-An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, eitherAn if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, eitherMaintainabilitylow
SA4015-Calling functions like math.Ceil on floats converted from integers doesn't do anything usefulCalling functions like math.Ceil on floats converted from integers doesn't do anything usefulConceptual Integrity, Functionalitylow
SA4016-Certain bitwise operations, such as x ^ 0, do not do anything usefulCertain bitwise operations, such as x ^ 0, do not do anything usefulFunctionalitylow
SA4017-A pure function's return value is discarded, making the call pointlessA pure function's return value is discarded, making the call pointlessFunctionalitylow
SA4018-Self-assignment of variablesSelf-assignment of variablesConceptual Integrity, Functionalitylow
SA4019-Multiple, identical build constraints in the same fileMultiple, identical build constraints in the same fileFunctionality, Conceptual Integritylow
SA4020-Unreachable case clause in a type switchIn a type switch like the following

type T struct{}
func (T) Read(b []byte) (int, error) { return 0, nil }

var v interface{} = T{}

switch v.(type) {
case io.Reader:
// ...
case T:
// unreachable
}
the second case clause can never be reached because T implements io.Reader and case clauses are evaluated in source order.
//non-comliant code

type T struct{}
func (T) Read(b []byte) (int, error) { return 0, nil }

var v interface{} = T{}

switch v.(type) {
case io.Reader:
// ...
case T:
// unreachable
}

Functionalitylow
SA4021-x = append(y) is equivalent to x = yx = append(y) is equivalent to x = yFunctionality, Conceptual Integritylow
SA4022-Comparing the address of a variable against nilCode such as 'if &x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer.Functionality, Conceptual Integritylow
SA4023-Impossible comparison of interface value with untyped nilUnder the covers, interfaces are implemented as two elements, a type T and a value V. V is a concrete value such as an int, struct or pointer, never an interface itself, and has type T. For instance, if we store the int value 3 in an interface, the resulting interface value has, schematically, (T=int, V=3). The value V is also known as the interface's dynamic value, since a given interface variable might hold different values V (and corresponding types T) during the execution of the program.

An interface value is nil only if the V and T are both unset, (T=nil, V is not set), In particular, a nil interface will always hold a nil type. If we store a nil pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (T=*int, V=nil). Such an interface value will therefore be non-nil even when the pointer value V inside is nil.
It's a good idea for functions that return errors always to use the error type in their signature (as we did above) rather than a concrete type such as *MyError, to help guarantee the error is created correctly. As an example, os.Open returns an error even though, if not nil, it's always of concrete type *os.PathError.

Similar situations to those described here can arise whenever interfaces are used. Just keep in mind that if any concrete value has been stored in the interface, the interface will not be nil.
//non-compliant code

func returnsError() error {
var p *MyError = nil
if bad() {
p = ErrBad
}
return p // Will always return a non-nil error.
}



//compliant code

func returnsError() error {
if bad() {
return ErrBad
}
return nil
}

Functionality, Conceptual Integritylow
SA4024-Checking for impossible return value from a builtin functionReturn values the len and cap builtins cannot be negative.//non-compliant code

func returnsError() error {
var p *MyError = nil
if bad() {
p = ErrBad
}
return p // Will always return a non-nil error.
}



//compliant code

func returnsError() error {
if bad() {
return ErrBad
}
return nil
}

Conceptual Integritylow
SA9003-Empty body in an if or else branchEmpty body in an if or else branchMaintainabilitylow
SA9004-Only the first constant has an explicit typen a constant declaration such as the following:

const (
First byte = 1
Second = 2
)
the constant Second does not have the same type as the constant First. This construct shouldn't be confused with

const (
First byte = iota
Second
)
where First and Second do indeed have the same type. The type is only passed on when no explicit value is assigned to the constant.

When declaring enumerations with explicit values it is therefore important not to write

const (
EnumFirst EnumType = 1
EnumSecond = 2
EnumThird = 3
)
This discrepancy in types can cause various confusing behaviors and bugs.
//non-comliant code

package pkg

const (
EnumFirst uint8 = 1
EnumSecond = 2
)

func fn(useFirst bool) {
x := EnumSecond
if useFirst {
x = EnumFirst
}
}
Conceptual Integritylow
ST1000-Incorrect or missing package commentPackages must have a package comment that is formatted according to the guidelines laid out inMaintainabilitylow
ST1001-Dot imports are discouragedDot imports that aren't in external test packages are discouraged.

The dot_import_whitelist option can be used to whitelist certain imports.
Maintainabilitylow
ST1003-Poorly chosen identifierIdentifiers, such as variable and package names, follow certain rules.

Maintainabilitylow
ST1005-Incorrectly formatted error stringError strings should not be capitalized (unless beginning with
proper nouns or acronyms) or end with punctuation, since they are
usually printed following other context. That is, use
fmt.Errorf("something bad") not fmt.Errorf("Something bad"), so
that log.Printf("Reading %s: %v", filename, err) formats without a
spurious capital letter mid-message.
Maintainability, Robustnesslow
ST1006-Poorly chosen receiver nameThe name of a method's receiver should be a reflection of its
identity; often a one or two letter abbreviation of its type
suffices (such as "c" or "cl" for "Client"). Don't use generic
names such as "me", "this" or "self", identifiers typical of
object-oriented languages that place more emphasis on methods as
opposed to functions. The name need not be as descriptive as that
of a method argument, as its role is obvious and serves no
documentary purpose. It can be very short as it will appear on
almost every line of every method of the type; familiarity admits
brevity. Be consistent, too: if you call the receiver "c" in one
method, don't call it "cl" in another.
Maintainabilitylow
ST1011-Poorly chosen name for variable of type time.Durationtime.Duration values represent an amount of time, which is represented as a count of nanoseconds. An expression like 5 * time.Microsecond yields the value 5000. It is therefore not appropriate to suffix a variable of type time.Duration with any time unit, such as Msec or Milli.

Maintainabilitylow
ST1012-Poorly chosen name for error variableError variables that are part of an API should be called errFoo or ErrFoo.Maintainabilitylow
ST1013-Should use constants for HTTP error codes, not magic numbersHTTP has a tremendous number of status codes. While some of those are well known (200, 400, 404, 500), most of them are not. The net/http package provides constants for all status codes that are part of the various specifications. It is recommended to use these constants instead of hard-coding magic numbers, to vastly improve the readability of your code.Maintainabilitylow
ST1015-A switch's default case should be the first or last caseA switch's default case should be the first or last caseMaintainability, Functionalitylow
ST1017-Don't use Yoda conditionsDon't use Yoda conditionsYoda conditions are conditions of the kind 'if 42 == x', where the literal is on the left side of the comparison. These are a common idiom in languages in which assignment is an expression, to avoid bugs of the kind 'if (x = 42)'. In Go, which doesn't allow for this kind of bug, we prefer the more idiomatic 'if x == 42'.

Maintainabilitylow
ST1018-Avoid zero-width and control characters in string literalsAvoid zero-width and control characters in string literals//non-compliant

import (

"fmt"
fumpt "fmt"
format "fmt"
_ "fmt"
)
Maintainabilitylow
ST1020-The documentation of an exported function should start with the function's nameDoc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.

If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
Maintainabilitylow
ST1021-The documentation of an exported type should start with type's nameDoc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.

If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
Maintainabilitylow
ST1022-The documentation of an exported variable or constant should start with variable's nameDoc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.

If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
Maintainabilitylow