3 import "honnef.co/go/tools/lint"
5 var Docs = map[string]*lint.Documentation{
7 Title: `Use plain channel send or receive instead of single-case select`,
8 Text: `Select statements with a single case can be replaced with a simple
26 Title: `Replace for loop with call to copy`,
27 Text: `Use copy() for copying elements from one slice to another.
31 for i, x := range src {
42 Title: `Omit comparison with boolean constant`,
54 Title: `Replace call to strings.Index with strings.Contains`,
57 if strings.Index(x, y) != -1 {}
61 if strings.Contains(x, y) {}`,
66 Title: `Replace call to bytes.Compare with bytes.Equal`,
69 if bytes.Compare(x, y) == 0 {}
73 if bytes.Equal(x, y) {}`,
78 Title: `Drop unnecessary use of the blank identifier`,
79 Text: `In many cases, assigning to the blank identifier is unnecessary.
96 Title: `Use for { ... } for infinite loops`,
97 Text: `For infinite loops, using for { ... } is the most idiomatic choice.`,
102 Title: `Simplify regular expression by using raw string literal`,
103 Text: `Raw string literals use ` + "`" + ` instead of " and do not support
104 any escape sequences. This means that the backslash (\) can be used
105 freely, without the need of escaping.
107 Since regular expressions have their own escape sequences, raw strings
108 can improve their readability.
112 regexp.Compile("\\A(\\w+) profile: total \\d+\\n\\z")
116 regexp.Compile(` + "`" + `\A(\w+) profile: total \d+\n\z` + "`" + `)`,
121 Title: `Simplify returning boolean expression`,
136 Title: `Omit redundant nil check on slices`,
137 Text: `The len function is defined for all slices, even nil ones, which have
138 a length of zero. It is not necessary to check if a slice is not nil
139 before checking that its length is not zero.
143 if x != nil && len(x) != 0 {}
152 Title: `Omit default slice index`,
153 Text: `When slicing, the second index defaults to the length of the value,
154 making s[n:len(s)] and s[n:] equivalent.`,
159 Title: `Use a single append to concatenate two slices`,
162 for _, e := range y {
168 x = append(x, y...)`,
173 Title: `Replace time.Now().Sub(x) with time.Since(x)`,
174 Text: `The time.Since helper has the same effect as using time.Now().Sub(x)
175 but is easier to read.
188 Title: `Use a type conversion instead of manually copying struct fields`,
189 Text: `Two struct types with identical fields can be converted between each
190 other. In older versions of Go, the fields had to have identical
191 struct tags. Since Go 1.8, however, struct tags are ignored during
192 conversions. It is thus not necessary to manually copy every field
211 Title: `Replace manual trimming with strings.TrimPrefix`,
212 Text: `Instead of using strings.HasPrefix and manual slicing, use the
213 strings.TrimPrefix function. If the string doesn't start with the
214 prefix, the original string will be returned. Using strings.TrimPrefix
215 reduces complexity, and avoids common bugs, such as off-by-one
220 if strings.HasPrefix(str, prefix) {
221 str = str[len(prefix):]
226 str = strings.TrimPrefix(str, prefix)`,
231 Title: `Use copy for sliding elements`,
232 Text: `copy() permits using the same source and destination slice, even with
233 overlapping ranges. This makes it ideal for sliding elements in a
238 for i := 0; i < n; i++ {
244 copy(bs[:n], bs[offset:])`,
249 Title: `Simplify make call by omitting redundant arguments`,
250 Text: `The make function has default values for the length and capacity
251 arguments. For channels and maps, the length defaults to zero.
252 Additionally, for slices the capacity defaults to the length.`,
257 Title: `Omit redundant nil check in type assertion`,
260 if _, ok := i.(T); ok && i != nil {}
264 if _, ok := i.(T); ok {}`,
269 Title: `Merge variable declaration and assignment`,
282 Title: `Omit redundant control flow`,
283 Text: `Functions that have no return value do not need a return statement as
284 the final statement of the function.
286 Switches in Go do not have automatic fallthrough, unlike languages
287 like C. It is not necessary to have a break statement as the final
288 statement in a case block.`,
293 Title: `Replace x.Sub(time.Now()) with time.Until(x)`,
294 Text: `The time.Until helper has the same effect as using x.Sub(time.Now())
295 but is easier to read.
308 Title: `Don't use fmt.Sprintf("%s", x) unnecessarily`,
309 Text: `In many instances, there are easier and more efficient ways of getting
310 a value's string representation. Whenever a value's underlying type is
311 a string already, or the type has a String method, they should be used
314 Given the following shared definitions
319 func (T2) String() string { return "Hello, world" }
325 we can simplify the following
340 Title: `Simplify error construction with fmt.Errorf`,
343 errors.New(fmt.Sprintf(...))
352 Title: `Range over the string directly`,
353 Text: `Ranging over a string will yield byte offsets and runes. If the offset
354 isn't used, this is functionally equivalent to converting the string
355 to a slice of runes and ranging over that. Ranging directly over the
356 string will be more performant, however, as it avoids allocating a new
357 slice, the size of which depends on the length of the string.
361 for _, r := range []rune(s) {}
365 for _, r := range s {}`,
370 Title: `Use bytes.Buffer.String or bytes.Buffer.Bytes`,
371 Text: `bytes.Buffer has both a String and a Bytes method. It is never
372 necessary to use string(buf.Bytes()) or []byte(buf.String()) – simply
373 use the other method.`,
378 Title: `Omit redundant nil check around loop`,
379 Text: `You can use range on nil slices and maps, the loop will simply never
380 execute. This makes an additional nil check around the loop
386 for _, x := range s {
393 for _, x := range s {
400 Title: `Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)`,
401 Text: `The sort.Ints, sort.Float64s and sort.Strings functions are easier to
402 read than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x))
403 and sort.Sort(sort.StringSlice(x)).
407 sort.Sort(sort.StringSlice(x))
416 Title: `Unnecessary guard around call to delete`,
417 Text: `Calling delete on a nil map is a no-op.`,
422 Title: `Use result of type assertion to simplify cases`,
427 Title: `Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header`,
428 Text: `The methods on net/http.Header, namely Add, Del, Get and Set, already
429 canonicalize the given header name.`,
434 Title: `Unnecessary guard around map access`,
436 Text: `When accessing a map key that doesn't exist yet, one
437 receives a zero value. Often, the zero value is a suitable value, for example when using append or doing integer math.
441 if _, ok := m["foo"]; ok {
442 m["foo"] = append(m["foo"], "bar")
444 m["foo"] = []string{"bar"}
449 m["foo"] = append(m["foo"], "bar")
453 if _, ok := m2["k"]; ok {
467 Title: `Elaborate way of sleeping`,
468 Text: `Using a select statement with a single case receiving
469 from the result of time.After is a very elaborate way of sleeping that
470 can much simpler be expressed with a simple call to time.Sleep.`,
475 Title: "Unnecessarily complex way of printing formatted string",
476 Text: `Instead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).`,
481 Title: "Unnecessary use of fmt.Sprint",
482 Text: `Calling fmt.Sprint with a single string argument is unnecessary and identical to using the string directly.`,