This page describes checks supported by go-critic linter.
Total number of checks is 106
Diagnostics try to find programming errors in the code. They also detect code that may be correct, but looks suspicious.
All diagnostics are enabled by default (unless it has “experimental” tag).
Name | Short description |
---|---|
appendAssign | Detects suspicious append result assignments |
argOrder | Detects suspicious arguments order |
badCall | Detects suspicious function calls |
badCond | Detects suspicious condition expressions |
badLock | Detects suspicious mutex lock/unlock operations |
badRegexp | Detects suspicious regexp patterns |
badSorting | Detects bad usage of sort package |
badSyncOnceFunc | Detects bad usage of sync.OnceFunc |
builtinShadowDecl | Detects top-level declarations that shadow the predeclared identifiers |
caseOrder | Detects erroneous case order inside switch statements |
codegenComment | Detects malformed ‘code generated’ file comments |
commentedOutCode | Detects commented-out code inside function bodies |
deferInLoop | Detects loops inside functions that use defer |
deprecatedComment | Detects malformed ‘deprecated’ doc-comments |
dupArg | Detects suspicious duplicated arguments |
dupBranchBody | Detects duplicated branch bodies inside conditional statements |
dupCase | Detects duplicated case clauses inside switch or select statements |
dupSubExpr | Detects suspicious duplicated sub-expressions |
dynamicFmtString | Detects suspicious formatting strings usage |
emptyDecl | Detects suspicious empty declarations blocks |
evalOrder | Detects unwanted dependencies on the evaluation order |
exitAfterDefer | Detects calls to exit/fatal inside functions that use defer |
externalErrorReassign | Detects suspicious reassignment of error from another package |
filepathJoin | Detects problems in filepath.Join() function calls |
flagDeref | Detects immediate dereferencing of flag package pointers |
flagName | Detects suspicious flag names |
mapKey | Detects suspicious map literal keys |
nilValReturn | Detects return statements those results evaluate to nil |
offBy1 | Detects various off-by-one kind of errors |
rangeAppendAll | Detects append all its data while range it |
regexpPattern | Detects suspicious regexp patterns |
returnAfterHttpError | Detects suspicious http.Error call without following return |
sloppyLen | Detects usage of len when result is obvious or doesn’t make sense |
sloppyReassign | Detects suspicious/confusing re-assignments |
sloppyTypeAssert | Detects redundant type assertions |
sortSlice | Detects suspicious sort.Slice calls |
sprintfQuotedString | Detects “%s” formatting directives that can be replaced with %q |
sqlQuery | Detects issue in Query() and Exec() calls |
syncMapLoadAndDelete | Detects sync.Map load+delete operations that can be replaced with LoadAndDelete |
truncateCmp | Detects potential truncation issues when comparing ints of different sizes |
uncheckedInlineErr | Detects unchecked errors in if statements |
unnecessaryDefer | Detects redundantly deferred calls |
weakCond | Detects conditions that are unsafe due to not being exhaustive |
Style checks suggest replacing some form of expression/statement with another one that is considered more idiomatic or simple.
Only non-opinionated style checks are enabled by default.
Name | Short description |
---|---|
assignOp | Detects assignments that can be simplified by using assignment operators |
boolExprSimplify | Detects bool expressions that can be simplified |
builtinShadow | Detects when predeclared identifiers are shadowed in assignments |
captLocal | Detects capitalized names for local variables |
commentFormatting | Detects comments with non-idiomatic formatting |
commentedOutImport | Detects commented-out imports |
defaultCaseOrder | Detects when default case in switch isn’t on 1st or last position |
deferUnlambda | Detects deferred function literals that can be simplified |
docStub | Detects comments that silence go lint complaints about doc-comment |
dupImport | Detects multiple imports of the same package under different aliases |
elseif | Detects else with nested if statement that can be replaced with else-if |
emptyFallthrough | Detects fallthrough that can be avoided by using multi case values |
emptyStringTest | Detects empty string checks that can be written more idiomatically |
exposedSyncMutex | Detects exposed methods from sync.Mutex and sync.RWMutex |
hexLiteral | Detects hex literals that have mixed case letter digits |
httpNoBody | Detects nil usages in http.NewRequest calls, suggesting http.NoBody as an alternative |
ifElseChain | Detects repeated if-else statements and suggests to replace them with switch statement |
importShadow | Detects when imported package names shadowed in the assignments |
initClause | Detects non-assignment statements inside if/switch init clause |
methodExprCall | Detects method expression call that can be replaced with a method call |
nestingReduce | Finds where nesting level could be reduced |
newDeref | Detects immediate dereferencing of new expressions |
octalLiteral | Detects old-style octal literals |
paramTypeCombine | Detects if function parameters could be combined by type and suggest the way to do it |
preferFilepathJoin | Detects concatenation with os.PathSeparator which can be replaced with filepath.Join |
ptrToRefParam | Detects input and output parameters that have a type of pointer to referential type |
redundantSprint | Detects redundant fmt.Sprint calls |
regexpMust | Detects regexp.Compile* that can be replaced with regexp.MustCompile*
|
regexpSimplify | Detects regexp patterns that can be simplified |
ruleguard | Runs user-defined rules using ruleguard linter |
singleCaseSwitch | Detects switch statements that could be better written as if statement |
stringConcatSimplify | Detects string concat operations that can be simplified |
stringsCompare | Detects strings.Compare usage |
switchTrue | Detects switch-over-bool statements that use explicit true tag value |
timeExprSimplify | Detects manual conversion to milli- or microseconds |
todoCommentWithoutDetail | Detects TODO comments without detail/assignee |
tooManyResultsChecker | Detects function with too many results |
typeAssertChain | Detects repeated type assertions and suggests to replace them with type switch statement |
typeDefFirst | Detects method declarations preceding the type definition itself |
typeSwitchVar | Detects type switches that can benefit from type guard clause with variable |
typeUnparen | Detects unneeded parenthesis inside type expressions and suggests to remove them |
underef | Detects dereference expressions that can be omitted |
unlabelStmt | Detects redundant statement labels |
unlambda | Detects function literals that can be simplified |
unnamedResult | Detects unnamed results that may benefit from names |
unnecessaryBlock | Detects unnecessary braced statement blocks |
unslice | Detects slice expressions that can be simplified to sliced expression itself |
valSwap | Detects value swapping code that are not using parallel assignment |
whyNoLint | Ensures that //nolint comments include an explanation |
wrapperFunc | Detects function calls that can be replaced with convenience wrappers |
yodaStyleExpr | Detects Yoda style expressions and suggests to replace them |
Performance checks tell you about potential issues that can make your code run slower than it could be.
All performance checks are disabled by default.
Name | Short description |
---|---|
appendCombine | Detects append chains to the same slice that can be done in a single append call |
equalFold | Detects unoptimal strings/bytes case-insensitive comparison |
hugeParam | Detects params that incur excessive amount of copying |
indexAlloc | Detects strings.Index calls that may cause unwanted allocs |
preferDecodeRune | Detects expressions like []rune(s)[0] that may cause unwanted rune slice allocation |
preferFprint | Detects fmt.Sprint(f/ln) calls which can be replaced with fmt.Fprint(f/ln) |
preferStringWriter | Detects w.Write or io.WriteString calls which can be replaced with w.WriteString |
preferWriteByte | Detects WriteRune calls with rune literal argument that is single byte and reports to use WriteByte instead |
rangeExprCopy | Detects expensive copies of for loop range expressions |
rangeValCopy | Detects loops that copy big objects during each iteration |
sliceClear | Detects slice clear loops, suggests an idiom that is recognized by the Go compiler |
stringXbytes | Detects redundant conversions between string and []byte |
[ diagnostic ]
Detects suspicious append result assignments.
Before:
p.positives = append(p.negatives, x)
p.negatives = append(p.negatives, y)
After:
p.positives = append(p.positives, x)
p.negatives = append(p.negatives, y)
[ performance ]
Detects append
chains to the same slice that can be done in a single append
call.
Before:
xs = append(xs, 1)
xs = append(xs, 2)
After:
xs = append(xs, 1, 2)
[ diagnostic ]
Detects suspicious arguments order.
Before:
strings.HasPrefix("#", userpass)
After:
strings.HasPrefix(userpass, "#")
[ style ]
Detects assignments that can be simplified by using assignment operators.
Before:
x = x * 2
After:
x *= 2
[ diagnostic ]
Detects suspicious function calls.
Before:
strings.Replace(s, from, to, 0)
After:
strings.Replace(s, from, to, -1)
[ diagnostic ]
Detects suspicious condition expressions.
Before:
for i := 0; i > n; i++ {
xs[i] = 0
}
After:
for i := 0; i < n; i++ {
xs[i] = 0
}
[ diagnostic experimental ]
Detects suspicious mutex lock/unlock operations.
Before:
mu.Lock(); mu.Unlock()
After:
mu.Lock(); defer mu.Unlock()
[ diagnostic experimental ]
Detects suspicious regexp patterns.
Before:
regexp.MustCompile(`(?:^aa|bb|cc)foo[aba]`)
After:
regexp.MustCompile(`^(?:aa|bb|cc)foo[ab]`)
[ diagnostic experimental ]
Detects bad usage of sort package.
Before:
xs = sort.StringSlice(xs)
After:
sort.Strings(xs)
[ diagnostic experimental ]
Detects bad usage of sync.OnceFunc.
Before:
sync.OnceFunc(foo)()
After:
fooOnce := sync.OnceFunc(foo); ...; fooOnce()
[ style experimental ]
Detects bool expressions that can be simplified.
Before:
a := !(elapsed >= expectElapsedMin)
b := !(x) == !(y)
After:
a := elapsed < expectElapsedMin
b := (x) == (y)
[ style opinionated ]
Detects when predeclared identifiers are shadowed in assignments.
Before:
len := 10
After:
length := 10
[ diagnostic experimental ]
Detects top-level declarations that shadow the predeclared identifiers.
Before:
type int struct {}
After:
type myInt struct {}
[ style ]
Detects capitalized names for local variables.
Before:
func f(IN int, OUT *int) (ERR error) {}
After:
func f(in int, out *int) (err error) {}
Checker parameters:
[ diagnostic ]
Detects erroneous case order inside switch statements.
Before:
switch x.(type) {
case ast.Expr:
fmt.Println("expr")
case *ast.BasicLit:
fmt.Println("basic lit") // Never executed
}
After:
switch x.(type) {
case *ast.BasicLit:
fmt.Println("basic lit") // Now reachable
case ast.Expr:
fmt.Println("expr")
}
[ diagnostic ]
Detects malformed ‘code generated’ file comments.
Before:
// This file was automatically generated by foogen
After:
// Code generated by foogen. DO NOT EDIT.
[ style ]
Detects comments with non-idiomatic formatting.
Before:
//This is a comment
After:
// This is a comment
[ diagnostic experimental ]
Detects commented-out code inside function bodies.
Before:
// fmt.Println("Debugging hard")
foo(1, 2)
After:
foo(1, 2)
Checker parameters:
[ style experimental ]
Detects commented-out imports.
Before:
import (
"fmt"
//"os"
)
After:
import (
"fmt"
)
[ style ]
Detects when default case in switch isn’t on 1st or last position.
Before:
switch {
case x > y:
// ...
default: // <- not the best position
// ...
case x == 10:
// ...
}
After:
switch {
case x > y:
// ...
case x == 10:
// ...
default: // <- last case (could also be the first one)
// ...
}
[ diagnostic experimental ]
Detects loops inside functions that use defer.
Before:
for _, filename := range []string{"foo", "bar"} {
f, err := os.Open(filename)
defer f.Close()
}
After:
func process(filename string) {
f, err := os.Open(filename)
defer f.Close()
}
/* ... */
for _, filename := range []string{"foo", "bar"} {
process(filename)
}
[ style experimental ]
Detects deferred function literals that can be simplified.
Before:
defer func() { f() }()
After:
defer f()
[ diagnostic ]
Detects malformed ‘deprecated’ doc-comments.
Before:
// deprecated, use FuncNew instead
func FuncOld() int
After:
// Deprecated: use FuncNew instead
func FuncOld() int
[ style experimental ]
Detects comments that silence go lint complaints about doc-comment.
Before:
// Foo ...
func Foo() {
}
After:
// (A) - remove the doc-comment stub
func Foo() {}
// (B) - replace it with meaningful comment
// Foo is a demonstration-only function.
func Foo() {}
[ diagnostic ]
Detects suspicious duplicated arguments.
Before:
copy(dst, dst)
After:
copy(dst, src)
[ diagnostic ]
Detects duplicated branch bodies inside conditional statements.
Before:
if cond {
println("cond=true")
} else {
println("cond=true")
}
After:
if cond {
println("cond=true")
} else {
println("cond=false")
}
[ diagnostic ]
Detects duplicated case clauses inside switch or select statements.
Before:
switch x {
case ys[0], ys[1], ys[2], ys[0], ys[4]:
}
After:
switch x {
case ys[0], ys[1], ys[2], ys[3], ys[4]:
}
[ style experimental ]
Detects multiple imports of the same package under different aliases.
Before:
import (
"fmt"
printing "fmt" // Imported the second time
)
After:
import(
"fmt"
)
[ diagnostic ]
Detects suspicious duplicated sub-expressions.
Before:
sort.Slice(xs, func(i, j int) bool {
return xs[i].v < xs[i].v // Duplicated index
})
After:
sort.Slice(xs, func(i, j int) bool {
return xs[i].v < xs[j].v
})
[ diagnostic experimental ]
Detects suspicious formatting strings usage.
Before:
fmt.Errorf(msg)
After:
fmt.Errorf("%s", msg)
[ style ]
Detects else with nested if statement that can be replaced with else-if.
Before:
if cond1 {
} else {
if x := cond2; x {
}
}
After:
if cond1 {
} else if x := cond2; x {
}
Checker parameters:
[ diagnostic experimental ]
Detects suspicious empty declarations blocks.
Before:
var()
After:
/* nothing */
[ style experimental ]
Detects fallthrough that can be avoided by using multi case values.
Before:
switch kind {
case reflect.Int:
fallthrough
case reflect.Int32:
return Int
}
After:
switch kind {
case reflect.Int, reflect.Int32:
return Int
}
[ style experimental ]
Detects empty string checks that can be written more idiomatically.
Before:
len(s) == 0
After:
s == ""
[ performance experimental ]
Detects unoptimal strings/bytes case-insensitive comparison.
Before:
strings.ToLower(x) == strings.ToLower(y)
After:
strings.EqualFold(x, y)
[ diagnostic experimental ]
Detects unwanted dependencies on the evaluation order.
Before:
return x, f(&x)
After:
err := f(&x)
return x, err
[ diagnostic ]
Detects calls to exit/fatal inside functions that use defer.
Before:
defer os.Remove(filename)
if bad {
log.Fatalf("something bad happened")
}
After:
defer os.Remove(filename)
if bad {
log.Printf("something bad happened")
return
}
[ style experimental ]
Detects exposed methods from sync.Mutex and sync.RWMutex.
Before:
type Foo struct{ ...; sync.Mutex; ... }
After:
type Foo struct{ ...; mu sync.Mutex; ... }
[ diagnostic experimental ]
Detects suspicious reassignment of error from another package.
Before:
io.EOF = nil
After:
/* don't do it */
[ diagnostic experimental ]
Detects problems in filepath.Join() function calls.
Before:
filepath.Join("dir/", filename)
After:
filepath.Join("dir", filename)
[ diagnostic ]
Detects immediate dereferencing of flag
package pointers.
Before:
b := *flag.Bool("b", false, "b docs")
After:
var b bool; flag.BoolVar(&b, "b", false, "b docs")
[ diagnostic ]
Detects suspicious flag names.
https://github.com/golang/go/issues/41792
Before:
b := flag.Bool(" foo ", false, "description")
After:
b := flag.Bool("foo", false, "description")
[ style experimental ]
Detects hex literals that have mixed case letter digits.
Before:
x := 0X12
y := 0xfF
After:
x := 0x12
// (A)
y := 0xff
// (B)
y := 0xFF
[ style experimental ]
Detects nil usages in http.NewRequest calls, suggesting http.NoBody as an alternative.
Before:
http.NewRequest("GET", url, nil)
After:
http.NewRequest("GET", url, http.NoBody)
[ performance ]
Detects params that incur excessive amount of copying.
Before:
func f(x [1024]int) {}
After:
func f(x *[1024]int) {}
Checker parameters:
[ style ]
Detects repeated if-else statements and suggests to replace them with switch statement.
Permits single else or else-if; repeated else-if or else + else-if will trigger suggestion to use switch statement. See EffectiveGo#switch.
Before:
if cond1 {
// Code A.
} else if cond2 {
// Code B.
} else {
// Code C.
}
After:
switch {
case cond1:
// Code A.
case cond2:
// Code B.
default:
// Code C.
}
Checker parameters:
[ style opinionated ]
Detects when imported package names shadowed in the assignments.
Before:
// "path/filepath" is imported.
filepath := "foo.txt"
After:
filename := "foo.txt"
[ performance ]
Detects strings.Index calls that may cause unwanted allocs.
See Go issue for details: https://github.com/golang/go/issues/25864
Before:
strings.Index(string(x), y)
After:
bytes.Index(x, []byte(y))
[ style opinionated experimental ]
Detects non-assignment statements inside if/switch init clause.
Before:
if sideEffect(); cond {
}
After:
sideEffect()
if cond {
}
[ diagnostic ]
Detects suspicious map literal keys.
Before:
_ = map[string]int{
"foo": 1,
"bar ": 2,
}
After:
_ = map[string]int{
"foo": 1,
"bar": 2,
}
[ style experimental ]
Detects method expression call that can be replaced with a method call.
Before:
f := foo{}
foo.bar(f)
After:
f := foo{}
f.bar()
[ style opinionated experimental ]
Finds where nesting level could be reduced.
Before:
for _, v := range a {
if v.Bool {
body()
}
}
After:
for _, v := range a {
if !v.Bool {
continue
}
body()
}
Checker parameters:
[ style ]
Detects immediate dereferencing of new
expressions.
Before:
x := *new(bool)
After:
x := false
[ diagnostic experimental ]
Detects return statements those results evaluate to nil.
Before:
if err == nil {
return err
}
After:
// (A) - return nil explicitly
if err == nil {
return nil
}
// (B) - typo in "==", change to "!="
if err != nil {
return err
}
[ style experimental opinionated ]
Detects old-style octal literals.
Before:
foo(02)
After:
foo(0o2)
[ diagnostic ]
Detects various off-by-one kind of errors.
Before:
xs[len(xs)]
After:
xs[len(xs)-1]
[ style opinionated ]
Detects if function parameters could be combined by type and suggest the way to do it.
Before:
func foo(a, b int, c, d int, e, f int, g int) {}
After:
func foo(a, b, c, d, e, f, g int) {}
[ performance experimental ]
Detects expressions like []rune(s)[0] that may cause unwanted rune slice allocation.
See Go issue for details: https://github.com/golang/go/issues/45260
Before:
r := []rune(s)[0]
After:
r, _ := utf8.DecodeRuneInString(s)
[ style experimental ]
Detects concatenation with os.PathSeparator which can be replaced with filepath.Join.
Before:
x + string(os.PathSeparator) + y
After:
filepath.Join(x, y)
[ performance experimental ]
Detects fmt.Sprint(f/ln) calls which can be replaced with fmt.Fprint(f/ln).
Before:
w.Write([]byte(fmt.Sprintf("%x", 10)))
After:
fmt.Fprintf(w, "%x", 10)
[ performance experimental ]
Detects w.Write or io.WriteString calls which can be replaced with w.WriteString.
Before:
w.Write([]byte("foo"))
After:
w.WriteString("foo")
[ performance experimental opinionated ]
Detects WriteRune calls with rune literal argument that is single byte and reports to use WriteByte instead.
Before:
w.WriteRune('\n')
After:
w.WriteByte('\n')
[ style opinionated experimental ]
Detects input and output parameters that have a type of pointer to referential type.
Before:
func f(m *map[string]int) (*chan *int)
After:
func f(m map[string]int) (chan *int)
[ diagnostic experimental ]
Detects append all its data while range it.
Before:
for _, n := range ns {
...
rs = append(rs, ns...) // append all slice data
}
}
After:
for _, n := range ns {
...
rs = append(rs, n)
}
}
[ performance ]
Detects expensive copies of for
loop range expressions.
Suggests to use pointer to array to avoid the copy using &
on range expression.
See Go issue for details: https://github.com/golang/go/issues/15812.
Before:
var xs [2048]byte
for _, x := range xs { // Copies 2048 bytes
// Loop body.
}
After:
var xs [2048]byte
for _, x := range &xs { // No copy
// Loop body.
}
Checker parameters:
[ performance ]
Detects loops that copy big objects during each iteration.
Suggests to use index access or take address and make use pointer instead.
Before:
xs := make([][1024]byte, length)
for _, x := range xs {
// Loop body.
}
After:
xs := make([][1024]byte, length)
for i := range xs {
x := &xs[i]
// Loop body.
}
Checker parameters:
[ style experimental ]
Detects redundant fmt.Sprint calls.
Before:
fmt.Sprint(x)
After:
x.String()
[ style ]
Detects regexp.Compile*
that can be replaced with regexp.MustCompile*
.
Before:
re, _ := regexp.Compile("const pattern")
After:
re := regexp.MustCompile("const pattern")
[ diagnostic experimental ]
Detects suspicious regexp patterns.
Before:
regexp.MustCompile(`google.com|yandex.ru`)
After:
regexp.MustCompile(`google\.com|yandex\.ru`)
[ style experimental opinionated ]
Detects regexp patterns that can be simplified.
Before:
regexp.MustCompile(`(?:a|b|c) [a-z][a-z]*`)
After:
regexp.MustCompile(`[abc] {3}[a-z]+`)
[ diagnostic experimental ]
Detects suspicious http.Error call without following return.
Before:
if err != nil { http.Error(...); }
After:
if err != nil { http.Error(...); return; }
[ style experimental ]
Runs user-defined rules using ruleguard linter.
Reads a rules file and turns them into go-critic checkers.
See https://github.com/quasilyte/go-ruleguard.
Before:
N/A
After:
N/A
Checker parameters:
[ style ]
Detects switch statements that could be better written as if statement.
Before:
switch x := x.(type) {
case int:
body()
}
After:
if x, ok := x.(int); ok {
body()
}
[ performance experimental ]
Detects slice clear loops, suggests an idiom that is recognized by the Go compiler.
Before:
for i := 0; i < len(buf); i++ { buf[i] = 0 }
After:
for i := range buf { buf[i] = 0 }
[ diagnostic ]
Detects usage of len
when result is obvious or doesn’t make sense.
Before:
len(arr) <= 0
After:
len(arr) == 0
[ diagnostic experimental ]
Detects suspicious/confusing re-assignments.
Before:
if err = f(); err != nil { return err }
After:
if err := f(); err != nil { return err }
[ diagnostic ]
Detects redundant type assertions.
Before:
func f(r io.Reader) interface{} {
return r.(interface{})
}
After:
func f(r io.Reader) interface{} {
return r
}
[ diagnostic experimental ]
Detects suspicious sort.Slice calls.
Before:
sort.Slice(xs, func(i, j) bool { return keys[i] < keys[j] })
After:
sort.Slice(kv, func(i, j) bool { return kv[i].key < kv[j].key })
[ diagnostic experimental ]
Detects “%s” formatting directives that can be replaced with %q.
Before:
fmt.Sprintf(`"%s"`, s)
After:
fmt.Sprintf(`%q`, s)
[ diagnostic experimental ]
Detects issue in Query() and Exec() calls.
Before:
_, err := db.Query("UPDATE ...")
After:
_, err := db.Exec("UPDATE ...")
[ style experimental ]
Detects string concat operations that can be simplified.
Before:
strings.Join([]string{x, y}, "_")
After:
x + "_" + y
[ performance ]
Detects redundant conversions between string and []byte.
Before:
copy(b, []byte(s))
After:
copy(b, s)
[ style experimental ]
Detects strings.Compare usage.
Before:
strings.Compare(x, y)
After:
x < y
[ style ]
Detects switch-over-bool statements that use explicit true
tag value.
Before:
switch true {...}
After:
switch {...}
[ diagnostic experimental ]
Detects sync.Map load+delete operations that can be replaced with LoadAndDelete.
Before:
v, ok := m.Load(k); if ok { m.Delete($k); f(v); }
After:
v, deleted := m.LoadAndDelete(k); if deleted { f(v) }
[ style experimental ]
Detects manual conversion to milli- or microseconds.
Before:
t.Unix() / 1000
After:
t.UnixMilli()
[ style opinionated experimental ]
Detects TODO comments without detail/assignee.
Before:
// TODO
fiiWithCtx(nil, a, b)
After:
// TODO(admin): pass context.TODO() instead of nil
fiiWithCtx(nil, a, b)
[ style opinionated experimental ]
Detects function with too many results.
Before:
func fn() (a, b, c, d float32, _ int, _ bool)
After:
func fn() (resultStruct, bool)
Checker parameters:
[ diagnostic experimental ]
Detects potential truncation issues when comparing ints of different sizes.
Before:
func f(x int32, y int16) bool {
return int16(x) < y
}
After:
func f(x int32, int16) bool {
return x < int32(y)
}
Checker parameters:
[ style experimental ]
Detects repeated type assertions and suggests to replace them with type switch statement.
Before:
if x, ok := v.(T1); ok {
// Code A, uses x.
} else if x, ok := v.(T2); ok {
// Code B, uses x.
} else if x, ok := v.(T3); ok {
// Code C, uses x.
}
After:
switch x := v.(T1) {
case cond1:
// Code A, uses x.
case cond2:
// Code B, uses x.
default:
// Code C, uses x.
}
[ style experimental ]
Detects method declarations preceding the type definition itself.
Before:
func (r rec) Method() {}
type rec struct{}
After:
type rec struct{}
func (r rec) Method() {}
[ style ]
Detects type switches that can benefit from type guard clause with variable.
Before:
switch v.(type) {
case int:
return v.(int)
case point:
return v.(point).x + v.(point).y
default:
return 0
}
After:
switch v := v.(type) {
case int:
return v
case point:
return v.x + v.y
default:
return 0
}
[ style opinionated ]
Detects unneeded parenthesis inside type expressions and suggests to remove them.
Before:
type foo [](func([](func())))
After:
type foo []func([]func())
[ diagnostic experimental ]
Detects unchecked errors in if statements.
Before:
if err := expr(); err2 != nil { /*...*/ }
After:
if err := expr(); err != nil { /*...*/ }
[ style ]
Detects dereference expressions that can be omitted.
Before:
(*k).field = 5
v := (*a)[5] // only if a is array
After:
k.field = 5
v := a[5]
Checker parameters:
[ style experimental ]
Detects redundant statement labels.
Before:
derp:
for x := range xs {
if x == 0 {
break derp
}
}
After:
for x := range xs {
if x == 0 {
break
}
}
[ style ]
Detects function literals that can be simplified.
Before:
func(x int) int { return fn(x) }
After:
fn
[ style opinionated experimental ]
Detects unnamed results that may benefit from names.
Before:
func f() (float64, float64)
After:
func f() (x, y float64)
Checker parameters:
[ style opinionated experimental ]
Detects unnecessary braced statement blocks.
Before:
x := 1
{
print(x)
}
After:
x := 1
print(x)
[ diagnostic experimental ]
Detects redundantly deferred calls.
Before:
func() {
defer os.Remove(filename)
}
After:
func() {
os.Remove(filename)
}
[ style ]
Detects slice expressions that can be simplified to sliced expression itself.
Before:
copy(b[:], values...)
After:
copy(b, values...)
[ style ]
Detects value swapping code that are not using parallel assignment.
Before:
*tmp = *x; *x = *y; *y = *tmp
After:
*x, *y = *y, *x
[ diagnostic experimental ]
Detects conditions that are unsafe due to not being exhaustive.
Before:
xs != nil && xs[0] != nil
After:
len(xs) != 0 && xs[0] != nil
[ style experimental ]
Ensures that //nolint
comments include an explanation.
Before:
//nolint
After:
//nolint // reason
[ style ]
Detects function calls that can be replaced with convenience wrappers.
Before:
wg.Add(-1)
After:
wg.Done()
[ style experimental ]
Detects Yoda style expressions and suggests to replace them.
Before:
return nil != ptr
After:
return ptr != nil