Code Inspections in Go
This topic lists all GoLand code inspections available in Go.
You can toggle specific inspections or change their severity level on the Editor | Inspections page of the IDE settings Control+Alt+S.
Probable bugs
Inspection | Description | Default Severity |
---|---|---|
'FailNow' in a non-test goroutine | Reports calls to Methods like For more information about Example: func TestFoo(t *testing.T) {
go func() {
t.Fatal("oops") //exits goroutine, not TestFoo
}()
} After the Replace with 'Error' and 'return' quick-fix is applied: func TestFoo(t *testing.T) {
go func() {
t.Error("oops")
return
}()
} | Warning |
'Unmarshal' is called with the incorrect argument | Reports calls to These calls will fail and return an error. For more information about Example: var animals []Animal
err := json.Unmarshal(jsonData, animals) // always returns an error After the Prepend '&' quick-fix is applied: var animals []Animal
err := json.Unmarshal(jsonData, &animals) | Warning |
'context.CancelFunc' is not called | Reports execution paths that do not call the The For more information about the Example: func _(ctx context.Context, cancel func()) {
var ctx2 context.Context
ctx2, cancel = context.WithCancel(ctx)
_ = ctx2
} | Warning |
Defer/go statement calls 'recover' or 'panic' directly | Reports Such statements are rarely useful and might indicate a misuse of the
For more information about go statements and panics handling, see Handling panics and Go statements in the Go Language Specification. | Weak warning |
Division by zero | Reports division by zero. Division by zero will lead to a runtime panic. Example: s := 3 / 0 | Warning |
Exceeded shift expression | Reports shift expressions that equal or exceed the width of the integer. All the bits of the left operand are shifted in such expression resulting in a constant value. The constant value indicates that either the shift offset is incorrect or the shift expression is redundant. Example: func shift(i int8) {
fmt.Println(i << 8) // always prints 0
} | Warning |
Imported package name as a name identifier | Reports declarations of variables, arguments or functions that overlap with the used import. While legal, such declarations will make using the package exported identifiers impossible after the declaration or create confusion when reading the code. Example: import "fmt"
import _ "fmt"
import iio "io"
func _() {
fmt.Println("demo")
demo := true
_, _ = iio.EOF, demo
}
func demo() (int, int) {
return 1, 2
}
func _() {
_, _ = iio.EOF, demo
fmt := "demo"
iio := 1
_, _ = iio, fmt
a, _ := demo()
_ = a
} Variable names | Warning |
Impossible interface type assertion | Reports impossible interface-to-interface type assertions. Checks for type assertions Example: var v interface {
Read()
}
_ = v.(io.Reader) The This inspection only reports if the language version is 1.15 or higher. | Warning |
Incorrect 'strings.Replace' count argument | Reports The count argument for how many times a string should be replaced should not be Example: a := strings.Replace("SSS", "S", "H", 0) // replaces nothing
b := strings.Replace("SSS", "S", "H", -1) // replaces all S occurrences with H | Warning |
Incorrect usage of 'fmt.Printf' and 'fmt.Println' functions | Reports incorrect usages of In their format strings, formatting functions use formatting verbs, like Example: fmt.Printf("id: %s", 42) The output of this function is fmt.Printf("id: %d", 42) | Weak warning |
Incorrect usage of the 'errors.As' function | Reports calls of the Such calls panic at runtime. For more information about the Example: _, err := os.Open("non-existing")
var pathError *fs.PathError
if errors.As(err, pathError) { // a pointer to *fs.PathError is required
} After the Prepend '&' quick-fix is applied: _, err := os.Open("non-existing")
var pathError *fs.PathError
if errors.As(err, &pathError) {
} This inspection only reports if the language version is 1.13 or higher. | Warning |
Incorrect usage of the 'sync/atomic' package | Reports assignment statements of the form Such operations are not atomic, and is a common misuse of the Example: import (
"sync/atomic"
)
type Counter uint64
func AtomicTests() {
x := uint64(1)
x = atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
_, x = 10, atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
x, _ = atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value"
} | Warning |
Integer to string type conversion | Reports conversions of Such conversions are discouraged because they return the UTF-8 representation of the Unicode code point For conversions that intend on using the code point, consider replacing them with Example: func main() {
a := 1
_ = string(a)
} After the Convert integer to rune quick-fix is applied: func main() {
a := 1
_ = string(rune(a))
} | Warning |
Invalid conversions of 'uintptr' to 'unsafe.Pointer' | Reports possibly incorrect conversions of A conversion from Example of invalid usage: nums := []int8{42, 24}
ptr := unsafe.Pointer(&nums[0])
addr := uintptr(ptr) // address is stored to a local variable
ptr = unsafe.Pointer(addr + uintptr(1)) Example of valid usage: nums := []int8{42, 24}
ptr := unsafe.Pointer(&nums[0])
ptr = unsafe.Pointer(uintptr(ptr) + uintptr(1)) | Warning |
Irregular usage of 'iota' | Reports irregular usage of The For details, see Iota in the Go specification. This inspection is triggered if two constant specifications have a textually identical expression list containing at least one reference to Consider omitting the redundant expression list or writing out the expression list every time. Example: const (
a = iota // 0
b // 1
c = iota // 2
) Triggers the inspection as the Example: const (
a, aa = iota, iota // 0, 0
b, bb // 1, 1
c, cc = iota + 40, iota // 42, 2
) Does not trigger the inspection as none of the expression lists is redundant. | Weak warning |
Leading whitespace in directive comment | Reports leading whitespaces before Go directives in comments. Go directives are not recognized if there is whitespace between The quick-fix removes the leading whitespace before the Go directive. Example: // go:embed file.txt
var File string After the quick fix is applied: //go:embed file.txt
var File string | Warning |
Locks mistakenly passed by value | Reports locks that are mistakenly passed by values. Accidentally copying a value containing a lock may cause both copies to work incorrectly. Generally, such values should be referred to through a pointer. A lock here means a type implementing Example: type SafeInt struct {
m sync.Mutex
i int
}
func (s SafeInt) Inc() { // mutex is copied
s.m.Lock()
s.i++
s.m.Unlock()
} After the Add pointer quick-fix is applied: type SafeInt struct {
m sync.Mutex
i int
}
func (s *SafeInt) Inc() {
s.m.Lock()
s.i++
s.m.Unlock()
} | Warning |
Loop variables captured by the func literal | Reports references to loop variables from within For more information about closures and goroutines, see What happens with closures running as goroutines? at go.dev. Example: for _, v := range []string{"a", "b", "c"} {
go func() {
fmt.Println(v) // output will likely be `c c c`, not `a b c`
}()
} After the quick-fix is applied: for _, v := range []string{"a", "b", "c"} {
v := v // `v` is copied now
go func() {
fmt.Println(v)
}()
} Note the analyzer only checks | Warning |
Malformed build tag | Reports malformed build tags and build tags in the incorrect location. The See Build Constraints at go.dev. Example: package main
// +build ignore
func main() {} The // +build ignore
package main
import "fmt" | Weak warning |
Malformed struct tag | Reports struct tags that do not conform to Go conventions for struct tags. According to these conventions, tag strings are a concatenation of optionally space-separated Also, the inspection checks that fields with tags are exported. Example of a valid tag: type Example struct {
Field int `json:"field" xml:"demo"`
} | Warning |
Mixed value and pointer receivers | Reports structures with methods that use a mixture of types: value and pointer receivers. Such usage is not recommended by the Go Documentation. For details, see Should I define methods on values or pointers? in the Go FAQ. Example: type S struct{
}
func (s *S) fun() {}
func (s S) fun2() {} | Weak warning |
Nilness analyzer | Reports problems caused by incorrect usage of the The IDE analyses data flow to determine if variables could have
| |
Non-standard signature for well-known function names | Reports methods with certain names in the following cases:
Such methods might indicate that the receiver type is intended to satisfy an interface from the standard library, but fails to do so because of the mistake in the method's signature. Example: type MyReader []byte
func (r MyReader) ReadByte(data []byte) (byte, error) {
} The usage is suspicious because it looks like an attempt to implement type MyReader []byte
func (r MyReader) ReadByte() (byte, error) {
} | Warning |
Reserved word used as name | Reports declarations of variables, arguments or functions that overlap with the built-in or reserved keyword. If you receive this error then your code might not be as explicit as possible and might confuse other users. Example: type byte struct{}
type string interface{} Types | Warning |
Shadowing variable | Reports declarations of variables that overlap with the declarations in the outer scope. As the meaning of the variable depends on the scope in that case, it may create confusion and lead to unintended consequences. Example: for i := 0; i < len(nums); i++ {
for i := 0; i < len(nums); i++ {
}
} The for i := 0; i < len(nums); i++ {
for j := 0; j < len(nums); j++ {
}
} | |
Unhandled error | Reports calls to functions and methods that do not handle the call result of the An API of such functions imply that their execution might finish unsuccessfully and they would return an error. Calls that do not handle the error result could be an indication of the API misuse. Example: os.Remove("non-existing") // error is ignored After the Handle error quick-fix is applied: err := os.Remove("non-existing") // error is handled
if err != nil {
return err
} | Warning |
Unused function or method call result | Reports calls to certain functions and methods that do not handle a call result. An API of such functions imply that users should call them mostly to get a return value and process it, not for side effects. Calls that do not handle the result could be an indication of a misuse of the API. Example: fmt.Errorf("error: %s", reason) // constructed error is ignored After the Introduce local variable quick-fix is applied: err := fmt.Errorf("error: %s", reason) | Warning |
Control flow issues
Inspection | Description | Default Severity |
---|---|---|
'defer' in the loop | Reports Using Example: func main() {
for {
field, err := db.Query("SELECT 1")
if err != nil {
// ...
}
defer field.Close()
// ...
}
} Calls of | Weak warning |
Assignment to a receiver | Reports assignments to method receivers. When you assign a value to the method receiver, the value will not be reflected outside of the method itself. Values will be reflected in subsequent calls from the same method. Example: package main
import "fmt"
type demo struct {
Val int
}
func (d *demo) change() {
d = nil // Assignment to the method receiver propagates only to callees but not to callers
d.myVal()
}
func (d *demo) myVal() {
fmt.Printf("my val: %#v\n", d)
}
func (d demo) change2() {
d = demo{} // Assignment to the method receiver doesn't propagate to other calls
d.myVal()
}
func (d *demo) change3() {
d.Val = 3
d.myVal()
}
func main() {
d := &demo{}
d.myVal()
d.change()
d.myVal()
d.Val = 2
d.change2()
d.myVal()
d.change3()
d.myVal()
} | Weak warning |
Infinite 'for' loop | Reports empty Running this code will make the CPU usage stay at maximum and will make the machine nearly unusable. Example: func main() {
for {
}
} | Warning |
Unreachable code | Reports code that can never be executed because there exists no control flow path to the code from the rest of the program. Example: func _() int {
print(1)
return 2
println() // This code is unreachable
return 0
} | Warning |
Code style issues
Inspection | Description | Default Severity |
---|---|---|
Comment has no leading space | Reports comments without a leading space. Note that the inspection works only if you select the Add a leading space to comments in Editor | Code Style | Go on the Other tab. Comments with a leading space can be easier to read since the first word is separated from the comment by a space. Example: //Prints JSON received from the createJSON function
func printJSON(output []byte) {
fmt.Println(string(output))
} | Weak warning |
Comment of exported element starts with the incorrect name | Reports comments that do not start with the name of the exported element. According to Comment Sentences at github.com/golang, this is a convention to begin a comment with the name of the exported element. Example: // represents a request to run a command.
type Request struct {} The comment starts with the struct description, not with the struct name. To stick to the convention rules, you can apply the Add prefix to comment quick-fix. After the quick-fix is applied, the comment looks as follows: // Request represents a request to run a command.
type Request struct {} // better | Weak warning |
Convert string literals | Reports double-quoted string literals that can be converted into raw string literals and raw string literals that can be converted to double-quoted string literals. Example: var s = "Hello\n \"World\"" After the quick fix is applied: var s = `Hello
"World"` There are two notes that you should take into account while converting double-quoted strings to raw strings:
| No highlighting, only fix |
Error string should not be capitalized or end with punctuation | Reports format issues in error strings. Example: err := fmt.Errorf("Cannot read the file!")
log.Printf("Reading %s: %v", file, err) According to Error Strings at github.com/golang, error strings should not be capitalized or end with punctuation because they might appear among other context. To fix the format, you can apply the Fix error string format quick-fix. After the quick-fix is applied, the error string will look like this: err := fmt.Errorf("cannot read the file")
log.Printf("Reading %s: %v", file, err) | Weak warning |
Exported element should have a comment | Reports exported declarations without a documentation comment. According to Doc Comments at github.com/golang, all top-level exported names should have doc comments. Also, for more information about comment sentences, see Comment Sentences at github.com/golang. To add a comment, you can apply the Add comment quick-fix. | No highlighting, only fix |
Exported element should have its own declaration | Reports exported variables or constants in comma-separated lists of declarations. Example: const C1, C3, C2, C44, C9, C11, C6 = 1, 2, 3, 1, 3, 2, 1 This declaration makes it hard to understand what value each constant has. You can apply the Extract to own declaration quick-fix to make this declaration more readable. After the quick-fix is applied to each constant, the declaration looks as follows: const (
C3 = 2
C2 = 3
C44 = 1
C9 = 3
C11 = 2
C6 = 1
C1 = 1
) | Weak warning |
Name starts with a package name | Reports exported names that start with a package name. This inspection does not report such names in the Example: package myPackage
func MyPackageGetIP() {
} The According to Package Names at github.com/golang, all references to names in a package will be done using the package name, so one can omit that name from the identifiers. For example, if you are in a package | Weak warning |
Receiver has a generic name | Reports receiver names like Example: func (self *MeterSnapshot) Rate5() float64 { return math.Float64frombits(self.rate5) } According to Receiver Names at github.com/golang, you should not use generic names such as "me", "this", or "self". These identifiers are typical for object-oriented languages and might give the method a special meaning. | Weak warning |
Struct initialization without field names | Reports structures that are initialized without specifying their field names. By default, the inspection is available only when you use the type that is defined in a different package. When initializing a structure, it is better to explicitly state field names in order to ensure that in case of changes in order of these fields or in names of the fields, they will correctly continue to be addressed. Example: _ = io.LimitedReader{nil, 10} The _ = io.LimitedReader{N: 10} The inspection has the following options:
| Weak warning |
Type parameter is declared in lowercase | Reports type parameters that are declared in lowercase. Examples in the official Go documentation use type parameters in uppercase. This inspection follows this uppercase rule for type parameters. func PrintSlice[t any](s []t) {
for _, v := range s{
print(v)
}
} The type parameter | No highlighting, only fix |
Unit-specific suffix for 'time.Duration' | Reports unit-specific suffixes in constant and variable names of The inspection comes from
Example: var timeoutSeconds = 5 * time.Second | Weak warning |
Unsorted imports | Reports unsorted imports. All Go programs should be formatted in the same way, the formatting rules are fixed by the gofmt tool. Those rules require imports to be sorted. Example of a wrong sorting: import (
"net"
"errors"
"fmt"
) You can apply the Sort imports quick-fix to fix the sorting. After the quick-fix is applied, the sorting looks as follows: import (
"errors"
"fmt"
"net"
) | Weak warning |
Usage of Snake_Case | Reports usage of snake case instead of camelcase for naming variables, constants and functions. According to MixedCaps at go.dev, camelcase is a convention in Go. Example: func get_external_IP() (string, error) {} The | Weak warning |
General
Inspection | Description | Default Severity |
---|---|---|
Deprecated element | Reports usages of deprecated elements. Example: // Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd.
const (
SEEK_SET int = 0 // seek relative to the origin of the file
SEEK_CUR int = 1 // seek relative to the current offset
SEEK_END int = 2 // seek relative to the end
) According to Constants at go.dev, | Warning |
Disabled GOPATH indexing | Reports disabled GOPATH indexing that might prevent proper resolution of code references. GOPATH stores your code base and all the files that are necessary for your development. Also, it includes packages that you download and install. If you disabled GOPATH indexing, only project and vendored packages are indexed. It might improve the overall performance but makes it impossible to use packages from GOPATH. | Weak warning |
Fuzzing is supported starting with Go 1.18 | Reports presence of fuzz tests when Go SDK version is less than 1.18 Fuzz testing is a method of automated testing that involves a directed search for input data that may cause a program crash or expose invalid behavior. Go supports fuzz testing starting from Go 1.18. Example of a fuzz test: func Div(a, b int) int {
return a / b
}
func FuzzDiv(f *testing.F) {
f.Fuzz(func(t *testing.T, a, b int) {
Div(a, b) // reports runtime error: integer divide by zero
})
} See Go Fuzzing for more information. | Warning |
Malformed test function name | Reports malformed names of tests, benchmarks, and examples. According to Package testing at go.dev, names must follow a special convention in order to make the go tool process them correctly. Example: func Testfoo(*testing.T) {} // the 'go' tool will not run this test After the Rename to quick-fix is applied: func TestFoo(*testing.T) {} | Warning |
Missing trailing comma before a newline in a composite literal | Reports a missing trailing comma before a newline in composite literals, function call arguments, and function parameter lists. Example: func f(f int) (
int,
bool // missing a trailing comma
){
println(1, 2 // missing a trailing comma
)
} | Error |
Redundant parentheses | Reports redundant parentheses in expressions and types. Example: func _(x (int), y ((string))) {
}
func _() {
_ = (1 + 1)
_ = (((1 + 1)))
_ = (((1 + 1))) + (((2 + 2)))
} After the Unwrap parentheses quick-fix is applied: func _(x int, y string) {
}
func _() {
_ = 1 + 1
_ = 1 + 1
_ = (1 + 1) + (2 + 2)
} | Weak warning |
Unexported return type of the exported function | Reports exported functions with unexported return types. Unexported types can be difficult to use when viewing documentation under go doc. Example: type hidden struct{}
func Exported() hidden { // Exported function with the `hidden` unexported return type
return hidden{}
} You can apply Export quick-fix to export the type. After the quick-fix is applied, type name will be capitalized: type Hidden struct{}
func Exported() Hidden { // Fixed
return Hidden{}
} | Warning |
Unnecessarily exported identifier | Reports exported identifiers that are used only in the package where they are defined but are not used in other packages. Making them exported is redundant and may clutter the API of the package. | |
Usage of 'interface{}' as a type | Reports usages of the empty interface as a type or type constraint. The empty interface denotes the set of all types. Go 1.18 introduced the more explicit alias The inspection is triggered for any usage of an empty interface as a type or type constraint. Aliases of the empty interface and interfaces that exclusively embed other empty interfaces do not trigger the inspection. Consider using the more explicit alias | No highlighting, only fix |
Usage of context.TODO() | Reports usages of According to the documentation at pkg.go.dev, you need to use Note that it is a temporary placeholder, and you must change it in the future to a more meaningful context (for example, |
Security
Inspection | Description | Default Severity |
---|---|---|
Vulnerable API usage | Reports usages of Vulnerable APIs of imported dependencies. Fixing the reported problems helps prevent your software from being compromised by an attacker. To solve a problem, you can update to a version where the vulnerability is fixed (if available) or switch to a dependency that doesn't have the vulnerability. Vulnerability data provided by Checkmarx (c). | Warning |
Declaration redundancy
Inspection | Description | Default Severity |
---|---|---|
Bool condition | Reports parts of boolean expressions that are either always Example: func isNonZero(x, y int) bool {
// the second comparison is either always true
// or not executed at all
return x > 0 && x > 0
} You can apply the Simplify expression quick-fix for the | Warning |
Empty declaration | Reports empty declarations. Empty declarations have no effect. If you remove them, you might improve code readability. Example: func main() {
const () // empty declaration
} You can apply the Delete empty declaration quick-fix to remove this declaration. | Warning |
Empty slice declared using a literal | Reports slice declarations with empty literal initializers used instead of An empty slice can be represented by Example: s := []string{} To change the declaration, use the Replace with nil slice declaration (changes semantics) quick-fix. After the quick-fix is applied: var s []string | Weak warning |
Redundant blank argument in range | Reports optional blank variables in range loops. When you use the Example: for a, _ = range v {} // `for a, _ =` is the same as `for a =` To remove the blank identifier, you can use the Delete blank argument quick-fix. After the quick-fix is applied, the code will look as follows: for a = range v {} | Warning |
Redundant comma | Reports commas that may be omitted in the end of argument lists and composite literals. The IDE suggests removing commas that are considered optional. Removing these commas might improve code readability. Example: s := []int{1, 2,} // the last comma may be omitted | Weak warning |
Redundant import alias | Reports aliases of imported packages that may be omitted. Usually, such aliases equal to the names of the imported packages, so aliases have no effect and one can use package names directly. Example: import fmt "fmt" The After the quick-fix is applied: import "fmt" | Weak warning |
Redundant second index in slices | Reports a redundant second index (a high bound) in slice expressions. Usually, the second index is optional. If you remove it, you might improve code readability. Example: var a []int
a = a[0:len(a)] // `a[0:len(a)]` is the same as `a[0:]` You can apply the Remove redundant index quick-fix to such cases. After the quick-fix is applied, this code looks as follows: var a []int
a = a[0:] | Warning |
Redundant semicolon | Reports redundant semicolons. Idiomatic Go programs have semicolons only in places such as For more information about semicolons in Go, see Semicolons at go.dev. Example: i := 1; | Weak warning |
Redundant type conversion | Reports type conversions that may be omitted. Example: var s = string("hello") The After the quick-fix is applied: var s = "hello" Sometimes conversion of a floating expression to a floating type can be intentional (see this issue as an example). In such cases, the IDE issues a warning about a possibly redundant conversion. | Weak warning |
Redundant types in composite literals | Reports redundant type declarations in composite literals. Example: nums := [][]int{[]int{1}, []int{2}} We have a slice of slices of the nums := [][]int{{1},{2}} For more information about composite literals, see Go Language Specification: Composite Literals at go.dev. | Warning |
Self assignment | Reports expressions that are assigned to themselves. Such assignments have no effect, removing them might improve code readability. Example: func importedVarSelfAssignment() {
http.ErrNotSupported = http.ErrNotSupported
} | Weak warning |
Type can be omitted | Reports types in variable and constant declarations that can be omitted since they can be inferred by the compiler. Such types are redundant, omitting them may improve readability of the code. Example: var s string = fmt.Sprintln("hi") The var s = fmt.Sprintln("hi") | Weak warning |
Unused constant | Reports constants that are defined but are never used in code. func main() {
const i = 100
} Unlike unused variables and imports, this code will compile. Unused constants might increase your code base and slow down program compilation. To delete the unused constant, consider using the Delete constant quick-fix. | Warning |
Unused exported function | Reports unused exported functions. In Go, a function is exported if it begins with a capital letter. Names of exported functions that were defined but never used are grayed out. // Unused exported function
func ExportedUnusedFunc() {
}
func main() {
fmt.Println("Hello")
} | Warning |
Unused exported type | Reports unused exported types in the type User struct {}
func main() {} The | Warning |
Unused function | Reports unused unexported functions. In Go, a function is unexported if it begins with a small letter. Names of unexported functions that were defined but never used are grayed out. // Unused unexported function
func unExportedUnusedFunc() {
}
func main() {
fmt.Println("Hello")
} | Warning |
Unused global variable | Reports global variables that are defined but are never used in code. If you have unused variables, the code will not compile. For more information about unused variables and imports, see Unused imports and variables at go.dev. func main() {
a := 422
} Code in the example will not compile. Therefore, it is highlighted as an error. You can apply two quick-fixes for such cases: Delete variable and Rename to _. The first quick-fix deletes the variable, the second one will convert the variable to a blank identifier. After the Rename to _ quick-fix is applied: func main() {
_ := 422
} | Warning |
Unused parameter | Reports unused function parameters. func main() {
printAll(
42,
"bird",
)
}
func printAll(
i int,
s string,
) {
fmt.Println(i)
} We call the printAll function passing | Warning |
Unused type | Reports unused types. type user struct {
FirstName string `json:"firstname"`
LastName string `json:"lastname"`
}
func main() {
} The | Warning |
Unused type parameter | Reports unused type parameters. func main() {
printAll(
42,
"bird",
)
}
func printAll[I int, S string](
i I,
s string,
) {
fmt.Println(i)
fmt.Println(s)
} The printAll function has two type parameters | Warning |