S1000 – Use plain channel send or receive

select with a single case can be replaced with a simple send or receive.

Before:

select {
case x := <-ch:
fmt.Println(x)
}

After:

x := <-ch
fmt.Println(x)

Available since

2017.1

S1001 – Replace with copy()

Use copy() for copying elements from one slice to another.

Before:

for i, x := range src {
dst[i] = x
}

After:

copy(dst, src)

Available since

2017.1

S1002 – Omit comparison with boolean constant

Before:

if x == true {}

After:

if x {}

Available since

2017.1

S1003 – Replace with strings.Contains

Before:

if strings.Index(x, y) != -1 {}

After:

if strings.Contains(x, y) {}

Available since

2017.1

S1004 – Replace with bytes.Equal

Before:

if bytes.Compare(x, y) == 0 {}

After:

if bytes.Equal(x, y) {}

Available since

2017.1

S1005 – Drop unnecessary use of the blank identifier

In many cases, assigning to the blank identifier is unnecessary.

Before:

for _ = range s {}
x, _ = someMap[key]
_ = <-ch

After:

for range s{}
x = someMap[key]
<-ch

Available since

2017.1

S1006 – Replace with for { ... }

For infinite loops, using for { ... } is the most idiomatic choice.

Available since

2017.1

S1007 – Simplify regular expression by using raw string literal

Raw string literals use ` instead of " and do not support any escape sequences.
This means that the backslash (\) can be used freely, without the need of escaping.

Since regular expressions have their own escape sequences,
raw strings can improve their readability.

Before:

regexp.Compile("\\A(\\w+) profile: total \\d+\\n\\z")

After:

regexp.Compile(`\A(\w+) profile: total \d+\n\z`)

Available since

2017.1

S1008 – Simplify returning boolean expression

Before:

if <expr> {
return true
}
return false

After:

return <expr>

Available since

2017.1

S1009 – Omit redundant nil check on slices

The len function is defined for all slices, even nil ones, which have a length of zero.
It is not necessary to check if a slice is not nil before checking that its length is not zero.

Before:

if x != nil && len(x) != 0 {}

After:

if len(x) != 0 {}

Available since

2017.1

S1010 – Omit default slice index

When slicing, the second index defaults to the length of the value, making s[n:len(s)] and s[n:] equivalent.

Available since

2017.1

S1011 – Use a single append to concatenate two slices

Before:

for _, e := range y {
x = append(x, e)
}

After:

x = append(x, y...)

Available since

2017.1

S1012 – Replace with time.Since(x)

The time.Since helper has the same effect as using time.Now().Sub(x) but is easier to read.

Before:

time.Now().Sub(x)

After:

time.Since(x)

Available since

2017.1

S1016 – Use a type conversion

Two struct types with identical fields can be converted between each other. In older versions of Go, the fields had to have identical struct tags. Since Go 1.8, however, struct tags are ignored during conversions. It is thus not necessary to manually copy every field individually.

Before:

var x T1
y := T2{
Field1: x.Field1,
Field2: x.Field2,
}

After:

var x T1
y := T2(x)

Available since

2017.1

S1017 – Replace with strings.TrimPrefix

Instead of using strings.HasPrefix and manual slicing, use the strings.TrimPrefix function. If the string doesn't start with the prefix, the original string will be returned. Using strings.TrimPrefix reduces complexity, and avoids common bugs, such as off-by-one mistakes.

Before:

if strings.HasPrefix(str, prefix) {
str = str[len(prefix):]
}

After:

str = strings.TrimPrefix(str, prefix)

Available since

2017.1

S1018 – Replace with copy()

copy() permits using the same source and destination slice, even with overlapping ranges. This makes it ideal for sliding elements in a slice.

Before:

for i := 0; i < n; i++ {
bs[i] = bs[offset+i]
}

After:

copy(bs[:n], bs[offset:])

Available since

2017.1

S1019 – Simplify make call

The make function has default values for the length and capacity arguments. For channels and maps, the length defaults to zero. Additionally, for slices the capacity defaults to the length.

Available since

2017.1

S1020 – Omit redundant nil check in type assertion

Before:

if _, ok := i.(T); ok && i != nil {}

After:

if _, ok := i.(T); ok {}

Available since

2017.1

S1021 – Merge variable declaration and assignment

Before:

var x uint
x = 1

After:

var x uint = 1

Available since

2017.1

S1023 – Omit redundant control flow

Functions that have no return value do not need a return statement as the final statement of the function.

Switches in Go do not have automatic fallthrough, unlike languages like C. It is not necessary to have a break statement as the final statement in a case block.

Available since

2017.1

S1024 – Replace with time.Until(x)

The time.Until helper has the same effect as using x.Sub(time.Now()) but is easier to read.

Before:

x.Sub(time.Now())

After:

time.Until(x)

Available since

2017.1

S1025 – Don't use fmt.Sprintf("%s", x) unnecessarily

In many instances, there are easier and more efficient ways of getting a value's string representation. Whenever a value's underlying type is a string already, or the type has a String method, they should be used directly.

S1028 – Replace with fmt.Errorf

Before:

errors.New(fmt.Sprintf(...))

After:

fmt.Errorf(...)

Available since

2017.1

S1029 – Range over the string

Ranging over a string will yield byte offsets and runes. If the offset isn't used, this is functionally equivalent to converting the string to a slice of runes and ranging over that. Ranging directly over the string will be more performant, however, as it avoids allocating a new slice, the size of which depends on the length of the string.

Before:

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

After:

for _, r := range s {}

Available since

2017.1

S1030 – Use bytes.Buffer.String or bytes.Buffer.Bytes

bytes.Buffer has both a String and a Bytes method. It is never necessary to use string(buf.Bytes()) or []byte(buf.String()) – simply use the other method.

Available since

2017.1

S1031 – Omit redundant nil check around loop

You can use range on nil slices and maps, the loop will simply never execute. This makes an additional nil check around the loop unnecessary.

Before:

if s != nil {
for _, x := range s {
...
}
}

After:

for _, x := range s {
...
}

Available since

2017.1

S1032 – Replace with sort.Ints(x), sort.Float64s(x), 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)).

Before:

sort.Sort(sort.StringSlice(x))

After:

sort.Strings(x)

Available since

2019.1

SA1000 – Invalid regular expression

Available since

2017.1

SA1001 – Invalid template

Available since

2017.1

SA1002 – Invalid format in time.Parse

Available since

2017.1

SA1003 – Unsupported argument to functions in encoding/binary

Available since

2017.1

SA1004 – Suspiciously small untyped constant in time.Sleep

Available since

2017.1

SA1005 – Invalid first argument to exec.Command

os/exec runs programs directly (using variants of the fork and exec system calls on Unix systems). This shouldn't be confused with running a command in a shell. The shell will allow for features such as input redirection, pipes, and general scripting. The shell is also responsible for splitting the user's input into a program name and its arguments. For example, the equivalent to ls / /tmp would be exec.Command("ls", "/", "/tmp").

If you want to run a command in a shell, consider using something like the following – but be aware that not all systems, particularly Windows, will have a /bin/sh program:

exec.Command("/bin/sh", "-c", "ls | grep Awesome")

Available since

2017.1

SA1006 – Printf with dynamic first argument and no further arguments

Using fmt.Printf with a dynamic first argument can lead to unexpected output. The first argument is a format string, where certain character combinations have special meaning. If, for example, a user were to enter a string such as Interest rate: 5% and you printed it with fmt.Printf(s), it would lead to the following output: Interest rate: 5%!(NOVERB).

Similarly, forming the first parameter via string concatenation with user input should be avoided for the same reason. When printing user input, either use a variant of fmt.Print, or use the %s Printf verb and pass the string as an argument.

SA1007 – Invalid URL in net/url.Parse

SA1008 – Non-canonical key in http.Header map

SA1011 – Various methods in the strings package expect valid UTF-8, but invalid input is provided

Available since

2017.1

SA1012 – A nil context.Context is being passed to a function, consider using context.TODO instead

Available since

2017.1

SA1013 – io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the second

Available since

2017.1

SA1014 – Non-pointer value passed to Unmarshal or Decode

Available since

2017.1

SA1015 – Using time.Tick in a way that will leak. Consider using time.NewTicker, and only use time.Tick in tests, commands and endless functions

Available since

2017.1

SA1016 – Trapping a signal that cannot be trapped

Available since

2017.1

SA1017 – Channels used with signal.Notify should be buffered

Available since

2017.1

SA1018 – strings.Replace called with n == 0, which does nothing

Available since

2017.1

SA1019 – Using a deprecated function, variable, constant or field

Available since

2017.1

SA1020 – Using an invalid host:port pair with a net.Listen-related function

Available since

2017.1

SA1021 – Using bytes.Equal to compare two net.IP

A net.IP stores an IPv4 or IPv6 address as a slice of bytes. The length of the slice for an IPv4 address, however, can be either 4 or 16 bytes long, using different ways of representing IPv4 addresses. In order to correctly compare two net.IPs, the net.IP.Equal method should be used, as it takes both representations into account.

Available since

2017.1

SA1023 – Modifying the buffer in an io.Writer implementation

Available since

2017.1

SA1024 – A string cutset contains duplicate characters, suggesting TrimPrefix or TrimSuffix should be used instead of TrimLeft or TrimRight

Available since

2017.1

SA1025 – it is not possible to use Reset's return value correctly

Available since

2019.1

SA2000 – sync.WaitGroup.Add called inside the goroutine, leading to a race condition

Available since

2017.1

SA2001 – Empty critical section, did you mean to defer the unlock?

Available since

2017.1

SA2002 – Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed

Even though T has a Close method and thus implements io.ReadCloser,
io.Reader will always match first. The method set of io.Reader is a subset of io.ReadCloser.
Thus it is impossible to match the second case without mtching the first case.

Structurally equivalent interfaces

A special case of the previous example are structurally identical interfaces. Given these declarations

SA5003 – Defers in infinite loops will never execute

SA5004 – for { select { ... with an empty default branch spins

A finalizer is a function associated with an object that runs when the garbage collector is ready to collect said object, that is when the object is no longer referenced by anything.

If the finalizer references the object, however, it will always remain as the final reference to that object, preventing the garbage collector from collecting the object. The finalizer will never run, and the object will never be collected, leading to a memory leak. That is why the finalizer should instead use its first argument to operate on the object. That way, the number of references can temporarily go to zero before the object is being passed to the finalizer.

Available since

2017.1

SA5006 – Slice index out of bounds

Available since

2017.1

SA5007 – Infinite recursive call

A function that calls itself recursively needs to have an exit condition. Otherwise it will recurse forever, until the system runs out of memory.

This issue can be caused by simple bugs such as forgetting adding an exit condition. It can also happen "on purpose". Some languages have tail call optimization which makes certain infinite recursive calls safe to use. Go, however, does not implement TCO, and as such a loop should be used instead.

Available since

2017.1

SA6000 – Using regexp.Match or related in a loop, should use regexp.Compile

Map keys must be comparable, which precludes the use of []byte. This usually leads to using string keys and converting []bytes to strings.

Normally, a conversion of []byte to string needs to copy the data and causes allocations. The compiler, however, recognizes m[string(b)] and uses the data of b directly, without copying it, because it knows that the data can't change during the map lookup. This leads to the counter-intuitive situation that

k := string(b)
println(m[k])
println(m[k])

will be less efficient than

println(m[string(b)])
println(m[string(b)])

because the first version needs to copy and allocate, while the second one does not.

SA6002 – Storing non-pointer values in sync.Pool allocates memory

A sync.Pool is used to avoid unnecessary allocations and reduce the amount of work the garbage collector has to do.

When passing a value that is not a pointer to a function that accepts an interface, the value needs to be placed on the heap, which means an additional allocation. Slices are a common thing to put in sync.Pools, and they're structs with 3 fields (length, capacity, and a pointer to an array). In order to avoid the extra allocation, one should store a pointer to the slice instead.

SA6003 – Converting a string to a slice of runes before ranging over it

You may want to loop over the runes in a string. Instead of converting the string to a slice of runes and looping over that, you can loop over the string itself. That is,

for _, r := range s {}

and

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

will yield the same values. The first version, however, will be faster and avoid unnecessary memory allocations.

Do note that if you are interested in the indices, ranging over a string and over a slice of runes will yield different indices. The first one yields byte offsets, while the second one yields indices in the slice of runes.

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

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

SA9005 – Trying to marshal a struct with no public fields nor custom marshaling

The encoding/json and encoding/xml packages only operate on exported fields in structs, not unexported ones.
It is usually an error to try to (un)marshal structs that only consist of unexported fields.

This check will not flag calls involving types that define custom marshaling behavior, e.g. via MarshalJSON methods. It will also not flag empty structs.

In this case, the test file cannot be in package foo because it uses bar/testutil, which imports foo. So we use the 'import .' form to let the file pretend to be part of package foo even though it is not. Except for this one case, do not use import . in your programs. It makes the programs much harder to read because it is unclear whether a name like Quux is a top-level identifier in the current package or in an imported package.

ST1005 – Incorrectly formatted error string

Error strings follow a set of guidelines to ensure uniformity and good composability.

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.
– Go Code Review Comments

Available since

2019.1

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.
– Go Code Review Comments

Available since

2019.1

ST1008 – A function's error value should be its last return value

A function's error value should be its last return value.

Available since

2019.1

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.

Available since

2019.1

ST1012 – Poorly chosen name for error variable

Error variables that are part of an API should be called errFoo or ErrFoo.

Available since

2019.1

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.