Rule | Description | Example | KPI | |
---|---|---|---|---|
S1001-Replace for loop with call to copy | Use 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, Efficiency | low |
S1002-Omit comparison with boolean constant | Omit comparison with boolean constant | //non-compliant code if x == true {} //compliant code if x {} | Functionality | low |
S1005-Drop unnecessary use of the blank identifier | In 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 | Functionality | low |
S1006-Use for { ... } for infinite loops | For infinite loops, using for { ... } is the most idiomatic choice. | Functionality | low | |
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) | Functionality | low |
S1020-Omit redundant nil check in type assertion | Omit redundant nil check in type assertion | //non-compliant code if _, ok := i.(T); ok && i != nil {} //compliant code if _, ok := i.(T); ok {} | Functionality | low |
S1021-Merge variable declaration and assignment | Merge variable declaration and assignment | //non-compliant code var x uint x = 1 //compliant code var x uint = 1 | Functionality | low |
S1031-Omit redundant nil check around loop | Omit redundant nil check around loop | Functionality | low | |
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) | Functionality | low |
S1033-Unnecessary guard around call to delete | Calling delete on a nil map is a no-op. | Functionality | low | |
S1034-Use result of type assertion to simplify cases | Use result of type assertion to simplify cases | Maintainability | low | |
S1036-Unnecessary guard around map access | When 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") | Functionality | low |
S1038-Unnecessarily complex way of printing formatted string | Instead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...). | Functionality | low | |
S1039-Unnecessary use of fmt.Sprint | Calling fmt.Sprint with a single string argument is unnecessary and identical to using the string directly. | Functionality | low | |
SA1018-strings.Replace called with n == 0, which does nothing | With n == 0, zero instances will be replaced. To replace all instances, use a negative number, or use strings.ReplaceAll. | Funtionality | low | |
SA4000-Boolean expression has identical expressions on both sides | Boolean expression has identical expressions on both sides | Functionality | low | |
SA4001-&*x gets simplified to x, it does not copy x | &*x gets simplified to x, it does not copy x | Functionality | low | |
SA4003-Comparing unsigned values against negative values is pointless | Comparing unsigned values against negative values is pointless | Functionality | low | |
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. | Functionality | low | |
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, either | 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, either | Maintainability | low | |
SA4015-Calling functions like math.Ceil on floats converted from integers doesn't do anything useful | Calling functions like math.Ceil on floats converted from integers doesn't do anything useful | Conceptual Integrity, Functionality | low | |
SA4016-Certain bitwise operations, such as x ^ 0, do not do anything useful | Certain bitwise operations, such as x ^ 0, do not do anything useful | Functionality | low | |
SA4017-A pure function's return value is discarded, making the call pointless | A pure function's return value is discarded, making the call pointless | Functionality | low | |
SA4018-Self-assignment of variables | Self-assignment of variables | Conceptual Integrity, Functionality | low | |
SA4019-Multiple, identical build constraints in the same file | Multiple, identical build constraints in the same file | Functionality, Conceptual Integrity | low | |
SA4020-Unreachable case clause in a type switch | In 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 } | Functionality | low |
SA4021-x = append(y) is equivalent to x = y | x = append(y) is equivalent to x = y | Functionality, Conceptual Integrity | low | |
SA4022-Comparing the address of a variable against nil | Code such as 'if &x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer. | Functionality, Conceptual Integrity | low | |
SA4023-Impossible comparison of interface value with untyped nil | Under 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 Integrity | low |
SA4024-Checking for impossible return value from a builtin function | Return 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 Integrity | low |
SA9003-Empty body in an if or else branch | Empty body in an if or else branch | Maintainability | low | |
SA9004-Only the first constant has an explicit type | n 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 Integrity | low |
ST1000-Incorrect or missing package comment | Packages must have a package comment that is formatted according to the guidelines laid out in | Maintainability | low | |
ST1001-Dot imports are discouraged | Dot imports that aren't in external test packages are discouraged. The dot_import_whitelist option can be used to whitelist certain imports. | Maintainability | low | |
ST1003-Poorly chosen identifier | Identifiers, such as variable and package names, follow certain rules. | Maintainability | low | |
ST1005-Incorrectly formatted error string | Error 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, Robustness | low | |
ST1006-Poorly chosen receiver name | The 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. | Maintainability | low | |
ST1011-Poorly chosen name for variable of type time.Duration | time.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. | Maintainability | low | |
ST1012-Poorly chosen name for error variable | Error variables that are part of an API should be called errFoo or ErrFoo. | Maintainability | low | |
ST1013-Should use constants for HTTP error codes, not magic numbers | HTTP 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. | Maintainability | low | |
ST1015-A switch's default case should be the first or last case | A switch's default case should be the first or last case | Maintainability, Functionality | low | |
ST1017-Don't use Yoda conditions | Don'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'. | Maintainability | low | |
ST1018-Avoid zero-width and control characters in string literals | Avoid zero-width and control characters in string literals | //non-compliant import ( "fmt" fumpt "fmt" format "fmt" _ "fmt" ) | Maintainability | low |
ST1020-The documentation of an exported function should start with the function's name | Doc 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. | Maintainability | low | |
ST1021-The documentation of an exported type should start with type's name | Doc 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. | Maintainability | low | |
ST1022-The documentation of an exported variable or constant should start with variable's name | Doc 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. | Maintainability | low |