staticcheck.io
下面是摘抄出来的几个:
SA6001 – Missing an optimization opportunity when indexing maps by byte slices
Map keys must be comparable, which precludes the use of byte slices. This usually leads to using string keys and converting byte slices to strings.
Normally, a conversion of a byte slice to a 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.
For some history on this optimization, check out commit f5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.
Available since
2017.1
SA6005 – Inefficient string comparison with strings.ToLower
or strings.ToUpper
Converting two strings to the same case and comparing them like so
if strings.ToLower(s1) == strings.ToLower(s2) {
…
}
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.
For a more in-depth explanation of this issue, see https://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/
Available since
2019.2
SA9003 – Empty body in an if or else branch
Available since
2017.1
S1000 – Use plain channel send or receive instead of single-case select
Select statements 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
S1003 – Replace call to strings.Index
with strings.Contains
Before:
if strings.Index(x, y) != -1 {}
After:
if strings.Contains(x, y) {}
Available since
2017.1
S1004 – Replace call to bytes.Compare
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
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
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
S1012 – Replace time.Now().Sub(x)
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 instead of manually copying struct fields
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 manual trimming 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 – Use copy
for sliding elements
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
S1024 – Replace x.Sub(time.Now())
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
S1030 – Use bytes.Buffer.String
or bytes.Buffer.Bytes
bytes.Buffer
has both a String
and a Bytes
method. It is almost never necessary to use string(buf.Bytes())
or []byte(buf.String())
– simply use the other method.
The only exception to this are map lookups. Due to a compiler optimization, m[string(buf.Bytes())]
is more efficient than m[buf.String()]
.
Available since
2017.1
S1032 – Use sort.Ints(x)
, sort.Float64s(x)
, and sort.Strings(x)
The sort.Ints
, sort.Float64s
and sort.Strings
functions are easier to read than sort.Sort(sort.IntSlice(x))
, sort.Sort(sort.Float64Slice(x))
and sort.Sort(sort.StringSlice(x))
.
Before:
sort.Sort(sort.StringSlice(x))
After:
sort.Strings(x)
Available since
2019.1
S1033 – Unnecessary guard around call to delete
Calling delete
on a nil map is a no-op.
Available since
2019.2
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
ST1017 – Don’t use Yoda conditions
Yoda conditions are conditions of the kind if 42 == x
, where the literal is on the left side of the comparison. These are a common idiom in languages in which assignment is an expression, to avoid bugs of the kind if (x = 42)
. In Go, which doesn’t allow for this kind of bug, we prefer the more idiomatic if x == 42
.
Available since
2019.2
ST1020 – The documentation of an exported function should start with the function’s name
non-default
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
See https://golang.org/doc/effective_go.html#commentary for more information on how to write good documentation.
Available since
2020.1
ST1021 – The documentation of an exported type should start with type’s name
non-default
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
If every doc comment begins with the name of the item it describes, you can use the doc
subcommand of the go
tool and run the output through grep.
See https://golang.org/doc/effective_go.html#commentary for more information on how to write good documentation.
Available since
2020.1
ST1022 – The documentation of an exported variable or constant should start with variable’s name
non-default
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
See https://golang.org/doc/effective_go.html#commentary for more information on how to write good documentation.
Available since
2020.1
QF1009 – Use time.Time.Equal instead of ==
operator
Available since
2021.1
QF1010 – Convert slice of bytes to string when printing it
Available since
2021.1
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)