Skip to content

Latest commit

 

History

History
3382 lines (2213 loc) · 47 KB

overview.md

File metadata and controls

3382 lines (2213 loc) · 47 KB

Checks overview

This page describes checks supported by go-critic linter.

Checkers

Total number of checks is 100 🚀

  • ✔️ checker is enabled by default.
  • ✅ checker is disabled by default.

Checkers from the "diagnostic" group

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
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
✔️ 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
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 reassigment 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
regexpPattern Detects suspicious regexp patterns
returnAfterHttpError Detects suspicious http.Error call without following return
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
unnecessaryDefer Detects redundantly deferred calls
weakCond Detects conditions that are unsafe due to not being exhaustive

Checkers from the "style" group

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
ioutilDeprecated Detects deprecated io/ioutil package usages
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
✔️ sloppyLen Detects usage of `len` when result is obvious or doesn't make sense
stringConcatSimplify Detects string concat operations that can be simplified
✔️ switchTrue Detects switch-over-bool statements that use explicit `true` tag value
timeExprSimplify Detects manual conversion to milli- or microseconds
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 unneded 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

Checkers from the "performance" group

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 byte literal argument 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

appendAssign

[ 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)

appendCombine

[ 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)

argOrder

[ diagnostic ]

Detects suspicious arguments order.

Before:

strings.HasPrefix("#", userpass)

After:

strings.HasPrefix(userpass, "#")

assignOp

[ style ]

Detects assignments that can be simplified by using assignment operators.

Before:

x = x * 2

After:

x *= 2

badCall

[ diagnostic ]

Detects suspicious function calls.

Before:

strings.Replace(s, from, to, 0)

After:

strings.Replace(s, from, to, -1)

badCond

[ 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
}

badLock

[ diagnostic experimental ]

Detects suspicious mutex lock/unlock operations.

Before:

mu.Lock(); mu.Unlock()

After:

mu.Lock(); defer mu.Unlock()

badRegexp

[ diagnostic experimental ]

Detects suspicious regexp patterns.

Before:

regexp.MustCompile(`(?:^aa|bb|cc)foo[aba]`)

After:

regexp.MustCompile(`^(?:aa|bb|cc)foo[ab]`)

badSorting

[ diagnostic experimental ]

Detects bad usage of sort package.

Before:

xs = sort.StringSlice(xs)

After:

sort.Strings(xs)

boolExprSimplify

[ style experimental ]

Detects bool expressions that can be simplified.

Before:

a := !(elapsed >= expectElapsedMin)
b := !(x) == !(y)

After:

a := elapsed < expectElapsedMin
b := (x) == (y)

builtinShadow

[ style opinionated ]

Detects when predeclared identifiers are shadowed in assignments.

Before:

len := 10

After:

length := 10

builtinShadowDecl

[ diagnostic experimental ]

Detects top-level declarations that shadow the predeclared identifiers.

Before:

type int struct {}

After:

type myInt struct {}

captLocal

[ 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:

  • @captLocal.paramsOnly whether to restrict checker to params only (default true)

caseOrder

[ 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")
}

codegenComment

[ diagnostic ]

Detects malformed 'code generated' file comments.

Before:

// This file was automatically generated by foogen

After:

// Code generated by foogen. DO NOT EDIT.

commentFormatting

[ style ]

Detects comments with non-idiomatic formatting.

Before:

//This is a comment

After:

// This is a comment

commentedOutCode

[ diagnostic experimental ]

Detects commented-out code inside function bodies.

Before:

// fmt.Println("Debugging hard")
foo(1, 2)

After:

foo(1, 2)

commentedOutImport

[ style experimental ]

Detects commented-out imports.

Before:

import (
	"fmt"
	//"os"
)

After:

import (
	"fmt"
)

defaultCaseOrder

[ 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)
	// ...
}

deferUnlambda

[ style experimental ]

Detects deferred function literals that can be simplified.

Before:

defer func() { f() }()

After:

defer f()

deprecatedComment

[ diagnostic ]

Detects malformed 'deprecated' doc-comments.

Before:

// deprecated, use FuncNew instead
func FuncOld() int

After:

// Deprecated: use FuncNew instead
func FuncOld() int

docStub

[ 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() {}

dupArg

[ diagnostic ]

Detects suspicious duplicated arguments.

Before:

copy(dst, dst)

After:

copy(dst, src)

dupBranchBody

[ 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")
}

dupCase

[ 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]:
}

dupImport

[ style experimental ]

Detects multiple imports of the same package under different aliases.

Before:

import (
	"fmt"
	priting "fmt" // Imported the second time
)

After:

import(
	"fmt"
)

dupSubExpr

[ 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
})

elseif

[ 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:

  • @elseif.skipBalanced whether to skip balanced if-else pairs (default true)

emptyDecl

[ diagnostic experimental ]

Detects suspicious empty declarations blocks.

Before:

var()

After:

/* nothing */

emptyFallthrough

[ 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
}

emptyStringTest

[ style experimental ]

Detects empty string checks that can be written more idiomatically.

Before:

len(s) == 0

After:

s == ""

equalFold

[ performance experimental ]

Detects unoptimal strings/bytes case-insensitive comparison.

Before:

strings.ToLower(x) == strings.ToLower(y)

After:

strings.EqualFold(x, y)

evalOrder

[ diagnostic experimental ]

Detects unwanted dependencies on the evaluation order.

Before:

return x, f(&x)

After:

err := f(&x)
return x, err

exitAfterDefer

[ 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
}

exposedSyncMutex

[ style experimental ]

Detects exposed methods from sync.Mutex and sync.RWMutex.

Before:

type Foo struct{ ...; sync.Mutex; ... }

After:

type Foo struct{ ...; mu sync.Mutex; ... }

externalErrorReassign

[ diagnostic experimental ]

Detects suspicious reassigment of error from another package.

Before:

io.EOF = nil

After:

/* don't do it */

filepathJoin

[ diagnostic experimental ]

Detects problems in filepath.Join() function calls.

Before:

filepath.Join("dir/", filename)

After:

filepath.Join("dir", filename)

flagDeref

[ 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")

flagName

[ diagnostic ]

Detects suspicious flag names.

golang/go#41792

Before:

b := flag.Bool(" foo ", false, "description")

After:

b := flag.Bool("foo", false, "description")

hexLiteral

[ 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

httpNoBody

[ 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)

hugeParam

[ performance ]

Detects params that incur excessive amount of copying.

Before:

func f(x [1024]int) {}

After:

func f(x *[1024]int) {}

Checker parameters:

  • @hugeParam.sizeThreshold size in bytes that makes the warning trigger (default 80)

ifElseChain

[ 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.
}

importShadow

[ style opinionated ]

Detects when imported package names shadowed in the assignments.

Before:

// "path/filepath" is imported.
filepath := "foo.txt"

After:

filename := "foo.txt"

indexAlloc

[ performance ]

Detects strings.Index calls that may cause unwanted allocs.

See Go issue for details: golang/go#25864

Before:

strings.Index(string(x), y)

After:

bytes.Index(x, []byte(y))

initClause

[ style opinionated experimental ]

Detects non-assignment statements inside if/switch init clause.

Before:

if sideEffect(); cond {
}

After:

sideEffect()
if cond {
}

ioutilDeprecated

[ style experimental ]

Detects deprecated io/ioutil package usages.

Before:

ioutil.ReadAll(r)

After:

io.ReadAll(r)

mapKey

[ diagnostic ]

Detects suspicious map literal keys.

Before:

_ = map[string]int{
	"foo": 1,
	"bar ": 2,
}

After:

_ = map[string]int{
	"foo": 1,
	"bar": 2,
}

methodExprCall

[ 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()

nestingReduce

[ 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:

  • @nestingReduce.bodyWidth min number of statements inside a branch to trigger a warning (default 5)

newDeref

[ style ]

Detects immediate dereferencing of new expressions.

Before:

x := *new(bool)

After:

x := false

nilValReturn

[ 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
}

octalLiteral

[ style experimental opinionated ]

Detects old-style octal literals.

Before:

foo(02)

After:

foo(0o2)

offBy1

[ diagnostic ]

Detects various off-by-one kind of errors.

Before:

xs[len(xs)]

After:

xs[len(xs)-1]

paramTypeCombine

[ 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) {}

preferDecodeRune

[ performance experimental ]

Detects expressions like []rune(s)[0] that may cause unwanted rune slice allocation.

See Go issue for details: golang/go#45260

Before:

r := []rune(s)[0]

After:

r, _ := utf8.DecodeRuneInString(s)

preferFilepathJoin

[ 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)

preferFprint

[ 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)

preferStringWriter

[ 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")

preferWriteByte

[ performance experimental ]

Detects WriteRune calls with byte literal argument and reports to use WriteByte instead.

Before:

w.WriteRune('\n')

After:

w.WriteByte('\n')

ptrToRefParam

[ 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)

rangeExprCopy

[ 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: golang/go#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:

  • @rangeExprCopy.sizeThreshold size in bytes that makes the warning trigger (default 512)

  • @rangeExprCopy.skipTestFuncs whether to check test functions (default true)

rangeValCopy

[ 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:

  • @rangeValCopy.sizeThreshold size in bytes that makes the warning trigger (default 128)

  • @rangeValCopy.skipTestFuncs whether to check test functions (default true)

redundantSprint

[ style experimental ]

Detects redundant fmt.Sprint calls.

Before:

fmt.Sprint(x)

After:

x.String()

regexpMust

[ style ]

Detects regexp.Compile* that can be replaced with regexp.MustCompile*.

Before:

re, _ := regexp.Compile("const pattern")

After:

re := regexp.MustCompile("const pattern")

regexpPattern

[ diagnostic experimental ]

Detects suspicious regexp patterns.

Before:

regexp.MustCompile(`google.com|yandex.ru`)

After:

regexp.MustCompile(`google\.com|yandex\.ru`)

regexpSimplify

[ 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]+`)

returnAfterHttpError

[ diagnostic experimental ]

Detects suspicious http.Error call without following return.

Before:

if err != nil { http.Error(...); }

After:

if err != nil { http.Error(...); return; }

ruleguard

[ 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:

  • @ruleguard.debug enable debug for the specified named rules group (default )

  • @ruleguard.failOn Determines the behavior when an error occurs while parsing ruleguard files. If flag is not set, log error and skip rule files that contain an error. If flag is set, the value must be a comma-separated list of error conditions.

    • 'import': rule refers to a package that cannot be loaded.
    • 'dsl': gorule file does not comply with the ruleguard DSL. (default )
  • @ruleguard.failOnError deprecated, use failOn param; if set to true, identical to failOn='all', otherwise failOn='' (default false)

  • @ruleguard.rules comma-separated list of gorule file paths. Glob patterns such as 'rules-*.go' may be specified (default )

singleCaseSwitch

[ 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()
}

sliceClear

[ 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 }

sloppyLen

[ style ]

Detects usage of len when result is obvious or doesn't make sense.

Before:

len(arr) <= 0

After:

len(arr) == 0

sloppyReassign

[ diagnostic experimental ]

Detects suspicious/confusing re-assignments.

Before:

if err = f(); err != nil { return err }

After:

if err := f(); err != nil { return err }

sloppyTypeAssert

[ diagnostic ]

Detects redundant type assertions.

Before:

func f(r io.Reader) interface{} {
	return r.(interface{})
}

After:

func f(r io.Reader) interface{} {
	return r
}

sortSlice

[ 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 })

sprintfQuotedString

[ diagnostic experimental ]

Detects "%s" formatting directives that can be replaced with %q.

Before:

fmt.Sprintf(`"%s"`, s)

After:

fmt.Sprintf(`%q`, s)

sqlQuery

[ diagnostic experimental ]

Detects issue in Query() and Exec() calls.

Before:

_, err := db.Query("UPDATE ...")

After:

_, err := db.Exec("UPDATE ...")

stringConcatSimplify

[ style experimental ]

Detects string concat operations that can be simplified.

Before:

strings.Join([]string{x, y}, "_")

After:

x + "_" + y

stringXbytes

[ performance ]

Detects redundant conversions between string and []byte.

Before:

copy(b, []byte(s))

After:

copy(b, s)

switchTrue

[ style ]

Detects switch-over-bool statements that use explicit true tag value.

Before:

switch true {...}

After:

switch {...}

syncMapLoadAndDelete

[ 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) }

timeExprSimplify

[ style experimental ]

Detects manual conversion to milli- or microseconds.

Before:

t.Unix() / 1000

After:

t.UnixMilli()

tooManyResultsChecker

[ 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:

  • @tooManyResultsChecker.maxResults maximum number of results (default 5)

truncateCmp

[ 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:

  • @truncateCmp.skipArchDependent whether to skip int/uint/uintptr types (default true)

typeAssertChain

[ 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.
}

typeDefFirst

[ 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() {}

typeSwitchVar

[ 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
}

typeUnparen

[ style opinionated ]

Detects unneded parenthesis inside type expressions and suggests to remove them.

Before:

type foo [](func([](func())))

After:

type foo []func([]func())

underef

[ 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:

  • @underef.skipRecvDeref whether to skip (*x).method() calls where x is a pointer receiver (default true)

unlabelStmt

[ 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
	}
}

unlambda

[ style ]

Detects function literals that can be simplified.

Before:

func(x int) int { return fn(x) }

After:

fn

unnamedResult

[ style opinionated experimental ]

Detects unnamed results that may benefit from names.

Before:

func f() (float64, float64)

After:

func f() (x, y float64)

Checker parameters:

  • @unnamedResult.checkExported whether to check exported functions (default false)

unnecessaryBlock

[ style opinionated experimental ]

Detects unnecessary braced statement blocks.

Before:

x := 1
{
	print(x)
}

After:

x := 1
print(x)

unnecessaryDefer

[ diagnostic experimental ]

Detects redundantly deferred calls.

Before:

func() {
	defer os.Remove(filename)
}

After:

func() {
	os.Remove(filename)
}

unslice

[ style ]

Detects slice expressions that can be simplified to sliced expression itself.

Before:

copy(b[:], values...)

After:

copy(b, values...)

valSwap

[ style ]

Detects value swapping code that are not using parallel assignment.

Before:

*tmp = *x; *x = *y; *y = *tmp

After:

*x, *y = *y, *x

weakCond

[ 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

whyNoLint

[ style experimental ]

Ensures that //nolint comments include an explanation.

Before:

//nolint

After:

//nolint // reason

wrapperFunc

[ style ]

Detects function calls that can be replaced with convenience wrappers.

Before:

wg.Add(-1)

After:

wg.Done()

yodaStyleExpr

[ style experimental ]

Detects Yoda style expressions and suggests to replace them.

Before:

return nil != ptr

After:

return ptr != nil