ruleDescriptionexampleKPI
S1023-Omit redundant control flowOmit redundant control flowFunctions that have no return value do not need a return statement as the final statement of the function.

Switches in Go do not have automatic fallthrough, unlike languages like C. It is not necessary to have a break statement as the final statement in a case block.
Functionality
S1029-Range over the string directlyRanging over a string will yield byte offsets and runes. If the offset isn't used, this is functionally equivalent to converting the string to a slice of runes and ranging over that. Ranging directly over the string will be more performant, however, as it avoids allocating a new slice, the size of which depends on the length of the string.

//non-compliant code

for _, r := range []rune(s) {}



//compliant code

for _, r := range s {}

Functonality, Efficiency
SA1000-Invalid regular expressionInvalid regular expressionRobustness
SA1001-Invalid templateInvalid templateRobustness
SA1002-Invalid format in time.ParseInvalid format in time.ParseRobustness
SA1003-Unsupported argument to functions in encoding/binaryThe encoding/binary package can only serialize types with known sizes. This precludes the use of the int and uint types, as their sizes differ on different architectures. Furthermore, it doesn't support serializing maps, channels, strings, or functions.Robustness
SA1005-Invalid first argument to exec.Commandos/exec runs programs directly (using variants of the fork and exec system calls on Unix systems). This shouldn't be confused with running a command in a shell. The shell will allow for features such as input redirection, pipes, and general scripting. The shell is also responsible for splitting the user's input into a program name and its arguments. //non-compliant code

ls / /tmp



//compliant code

exec.Command("ls", "/", "/tmp")

Robustness
SA1007-Invalid URL in net/url.ParseInvalid URL in net/url.ParseRobustness
SA1010-(*regexp.Regexp).FindAll called with n == 0, which will always return zero resultsIf n >= 0, the function returns at most n matches/submatches. To return all results, specify a negative number.Robustness
SA1011-Various methods in the strings package expect valid UTF-8, but invalid input is providedVarious methods in the strings package expect valid UTF-8, but invalid input is providedFunctionality
SA1013-io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the secondio.Seeker.Seek is being called with the whence constant as the first argument, but it should be the secondRobustness
SA1014-Non-pointer value passed to Unmarshal or DecodeNon-pointer value passed to Unmarshal or DecodeRobustness
SA1020-Using an invalid host:port pair with a net.Listen-related functionUsing an invalid host:port pair with a net.Listen-related functionRobustness
SA1021-Using bytes.Equal to compare two net.IPA net.IP stores an IPv4 or IPv6 address as a slice of bytes. The length of the slice for an IPv4 address, however, can be either 4 or 16 bytes long, using different ways of representing IPv4 addresses. In order to correctly compare two net.IPs, the net.IP.Equal method should be used, as it takes both representations into account.Robustness
SA1023-Modifying the buffer in an io.Writer implementationWrite must not modify the slice data, even temporarily.Robustness
SA1026-Cannot marshal channels or functionsCannot marshal channels or functionsRobustness, Functionality
SA1027-Atomic access to 64-bit variable must be 64-bit alignedOn ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to arrange for 64-bit alignment of 64-bit words accessed atomically. The first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned.

You can use the structlayout tool to inspect the alignment of fields in a struct.
Robustness
SA1029-Inappropriate key in call to context.WithValueThe provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys.

To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.
Robustness
SA1030-Invalid argument in call to a strconv functionThis check validates the format, number base and bit size arguments of the various parsing and formatting functions in strconv.

Robustness
SA2000-sync.WaitGroup.Add called inside the goroutine, leading to a race conditionsync.WaitGroup.Add called inside the goroutine, leading to a race conditionRobustness
SA2002-Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowedCalled testing.T.FailNow or SkipNow in a goroutine, which isn't allowedRobustness
SA2003-Deferred Lock right after locking, likely meant to defer Unlock insteadDeferred Lock right after locking, likely meant to defer Unlock insteadRobustness
SA3000-TestMain doesn't call os.Exit, hiding test failuresTest executables (and in turn 'go test') exit with a non-zero status code if any tests failed. When specifying your own TestMain function, it is your responsibility to arrange for this, by calling os.Exit with the correct code. The correct code is returned by (*testing.M).Run, so the usual way of implementing TestMain is to end it with os.Exit(m.Run()).Functionality
SA4012-Comparing a value against NaN even though no value is equal to NaNComparing a value against NaN even though no value is equal to NaNConceptual Integrity, Robustness
SA5002-The empty for loop (for {}) spins and can block the schedulerThe empty for loop (for {}) spins and can block the schedulerRobustness, Conceptual Integrity
SA5003-Defers in infinite loops will never executeDefers in infinite loops will never executeRobustness, Conceptual Integrity
SA5005-The finalizer references the finalized object, preventing garbage collectionA finalizer is a function associated with an object that runs when the garbage collector is ready to collect said object, that is when the object is no longer referenced by anything.

If the finalizer references the object, however, it will always remain as the final reference to that object, preventing the garbage collector from collecting the object. The finalizer will never run, and the object will never be collected, leading to a memory leak. That is why the finalizer should instead use its first argument to operate on the object. That way, the number of references can temporarily go to zero before the object is being passed to the finalizer.
Efficiency, Robustness
SA5007-Infinite recursive callA function that calls itself recursively needs to have an exit condition. Otherwise it will recurse forever, until the system runs out of memory.

This issue can be caused by simple bugs such as forgetting to add an exit condition. It can also happen "on purpose". Some languages have tail call optimization which makes certain infinite recursive calls safe to use. Go, however, does not implement TCO, and as such a loop should be used instead.
Robustness
SA5008-Invalid struct tagInvalid struct tagRobustness
SA5009-Invalid Printf callInvalid Printf callRobustness
SA5010-Impossible type assertionSome type assertions can be statically proven to be impossible. This is the case when the method sets of both arguments of the type assertion conflict with each other, for example by containing the same method with different signatures.

The Go compiler already applies this check when asserting from an interface value to a concrete type. If the concrete type misses methods from the interface, or if function signatures don't match, then the type assertion can never succeed.

This check applies the same logic when asserting from one interface to another. If both interface types contain the same method but with different signatures, then the type assertion can never succeed, either.
Robustness, Conceptual Integrity
SA5011-Possible nil pointer dereferenceA pointer is being dereferenced unconditionally, while also being checked against nil in another place. This suggests that the pointer may be nil and dereferencing it may panic. This is commonly a result of improperly ordered code or missing return statements. Staticcheck tries to deduce which functions abort control flow. //non-comliant code

func Log(msg string, level int) {
fmt.Println(msg)
if level == levelFatal {
os.Exit(1)
}
}

func Fatal(msg string) {
Log(msg, levelFatal)
}

func fn(x *int) {
if x == nil {
Fatal("unexpected nil pointer")
}
fmt.Println(*x)
}


//compliant code

func Log(msg string, level int) {
fmt.Println(msg)
if level == levelFatal {
os.Exit(1)
}
}

func Fatal(msg string) {
Log(msg, levelFatal)
panic("unreachable")
}

func fn(x *int) {
if x == nil {
Fatal("unexpected nil pointer")
}
fmt.Println(*x)
}
Robustess
SA6002-Storing non-pointer values in sync.Pool allocates memoryA sync.Pool is used to avoid unnecessary allocations and reduce the amount of work the garbage collector has to do.

When passing a value that is not a pointer to a function that accepts an interface, the value needs to be placed on the heap, which means an additional allocation. Slices are a common thing to put in sync.Pools, and they're structs with 3 fields (length, capacity, and a pointer to an array). In order to avoid the extra allocation, one should store a pointer to the slice instead.
Efficieny
SA6005-Inefficient string comparison with strings.ToLower or strings.ToUpperConverting two strings to the same case and comparing them like so

if strings.ToLower(s1) == strings.ToLower(s2) {
...
}
is significantly more expensive than comparing them with strings.EqualFold(s1, s2). This is due to memory usage as well as computational complexity.

strings.ToLower will have to allocate memory for the new strings, as well as convert both strings fully, even if they differ on the very first byte. strings.EqualFold, on the other hand, compares the strings one character at a time. It doesn't need to create two intermediate strings and can return as soon as the first non-matching character has been found.

Robustness
SA9001-Defers in range loops may not run when you expect them toDefers in range loops may not run when you expect them toConceptual Integrity, Robustness