honnef.co/go/tools@v0.4.7/staticcheck/doc.go (about) 1 // Package staticcheck contains analyzes that find bugs and performance issues. 2 // Barring the rare false positive, any code flagged by these analyzes needs to be fixed. 3 package staticcheck 4 5 import "honnef.co/go/tools/analysis/lint" 6 7 var Docs = lint.Markdownify(map[string]*lint.RawDocumentation{ 8 "SA1000": { 9 Title: `Invalid regular expression`, 10 Since: "2017.1", 11 Severity: lint.SeverityError, 12 MergeIf: lint.MergeIfAny, 13 }, 14 15 "SA1001": { 16 Title: `Invalid template`, 17 Since: "2017.1", 18 Severity: lint.SeverityError, 19 MergeIf: lint.MergeIfAny, 20 }, 21 22 "SA1002": { 23 Title: `Invalid format in \'time.Parse\'`, 24 Since: "2017.1", 25 Severity: lint.SeverityError, 26 MergeIf: lint.MergeIfAny, 27 }, 28 29 "SA1003": { 30 Title: `Unsupported argument to functions in \'encoding/binary\'`, 31 Text: `The \'encoding/binary\' package can only serialize types with known sizes. 32 This precludes the use of the \'int\' and \'uint\' types, as their sizes 33 differ on different architectures. Furthermore, it doesn't support 34 serializing maps, channels, strings, or functions. 35 36 Before Go 1.8, \'bool\' wasn't supported, either.`, 37 Since: "2017.1", 38 Severity: lint.SeverityError, 39 MergeIf: lint.MergeIfAny, 40 }, 41 42 "SA1004": { 43 Title: `Suspiciously small untyped constant in \'time.Sleep\'`, 44 Text: `The \'time\'.Sleep function takes a \'time.Duration\' as its only argument. 45 Durations are expressed in nanoseconds. Thus, calling \'time.Sleep(1)\' 46 will sleep for 1 nanosecond. This is a common source of bugs, as sleep 47 functions in other languages often accept seconds or milliseconds. 48 49 The \'time\' package provides constants such as \'time.Second\' to express 50 large durations. These can be combined with arithmetic to express 51 arbitrary durations, for example \'5 * time.Second\' for 5 seconds. 52 53 If you truly meant to sleep for a tiny amount of time, use 54 \'n * time.Nanosecond\' to signal to Staticcheck that you did mean to sleep 55 for some amount of nanoseconds.`, 56 Since: "2017.1", 57 Severity: lint.SeverityWarning, 58 MergeIf: lint.MergeIfAny, 59 }, 60 61 "SA1005": { 62 Title: `Invalid first argument to \'exec.Command\'`, 63 Text: `\'os/exec\' runs programs directly (using variants of the fork and exec 64 system calls on Unix systems). This shouldn't be confused with running 65 a command in a shell. The shell will allow for features such as input 66 redirection, pipes, and general scripting. The shell is also 67 responsible for splitting the user's input into a program name and its 68 arguments. For example, the equivalent to 69 70 ls / /tmp 71 72 would be 73 74 exec.Command("ls", "/", "/tmp") 75 76 If you want to run a command in a shell, consider using something like 77 the following – but be aware that not all systems, particularly 78 Windows, will have a \'/bin/sh\' program: 79 80 exec.Command("/bin/sh", "-c", "ls | grep Awesome")`, 81 Since: "2017.1", 82 Severity: lint.SeverityWarning, 83 MergeIf: lint.MergeIfAny, 84 }, 85 86 "SA1006": { 87 Title: `\'Printf\' with dynamic first argument and no further arguments`, 88 Text: `Using \'fmt.Printf\' with a dynamic first argument can lead to unexpected 89 output. The first argument is a format string, where certain character 90 combinations have special meaning. If, for example, a user were to 91 enter a string such as 92 93 Interest rate: 5% 94 95 and you printed it with 96 97 fmt.Printf(s) 98 99 it would lead to the following output: 100 101 Interest rate: 5%!(NOVERB). 102 103 Similarly, forming the first parameter via string concatenation with 104 user input should be avoided for the same reason. When printing user 105 input, either use a variant of \'fmt.Print\', or use the \'%s\' Printf verb 106 and pass the string as an argument.`, 107 Since: "2017.1", 108 Severity: lint.SeverityWarning, 109 MergeIf: lint.MergeIfAny, 110 }, 111 112 "SA1007": { 113 Title: `Invalid URL in \'net/url.Parse\'`, 114 Since: "2017.1", 115 Severity: lint.SeverityError, 116 MergeIf: lint.MergeIfAny, 117 }, 118 119 "SA1008": { 120 Title: `Non-canonical key in \'http.Header\' map`, 121 Text: `Keys in \'http.Header\' maps are canonical, meaning they follow a specific 122 combination of uppercase and lowercase letters. Methods such as 123 \'http.Header.Add\' and \'http.Header.Del\' convert inputs into this canonical 124 form before manipulating the map. 125 126 When manipulating \'http.Header\' maps directly, as opposed to using the 127 provided methods, care should be taken to stick to canonical form in 128 order to avoid inconsistencies. The following piece of code 129 demonstrates one such inconsistency: 130 131 h := http.Header{} 132 h["etag"] = []string{"1234"} 133 h.Add("etag", "5678") 134 fmt.Println(h) 135 136 // Output: 137 // map[Etag:[5678] etag:[1234]] 138 139 The easiest way of obtaining the canonical form of a key is to use 140 \'http.CanonicalHeaderKey\'.`, 141 Since: "2017.1", 142 Severity: lint.SeverityWarning, 143 MergeIf: lint.MergeIfAny, 144 }, 145 146 "SA1010": { 147 Title: `\'(*regexp.Regexp).FindAll\' called with \'n == 0\', which will always return zero results`, 148 Text: `If \'n >= 0\', the function returns at most \'n\' matches/submatches. To 149 return all results, specify a negative number.`, 150 Since: "2017.1", 151 Severity: lint.SeverityWarning, 152 MergeIf: lint.MergeIfAny, // MergeIfAny if we only flag literals, not named constants 153 }, 154 155 "SA1011": { 156 Title: `Various methods in the \"strings\" package expect valid UTF-8, but invalid input is provided`, 157 Since: "2017.1", 158 Severity: lint.SeverityError, 159 MergeIf: lint.MergeIfAny, 160 }, 161 162 "SA1012": { 163 Title: `A nil \'context.Context\' is being passed to a function, consider using \'context.TODO\' instead`, 164 Since: "2017.1", 165 Severity: lint.SeverityWarning, 166 MergeIf: lint.MergeIfAny, 167 }, 168 169 "SA1013": { 170 Title: `\'io.Seeker.Seek\' is being called with the whence constant as the first argument, but it should be the second`, 171 Since: "2017.1", 172 Severity: lint.SeverityWarning, 173 MergeIf: lint.MergeIfAny, 174 }, 175 176 "SA1014": { 177 Title: `Non-pointer value passed to \'Unmarshal\' or \'Decode\'`, 178 Since: "2017.1", 179 Severity: lint.SeverityError, 180 MergeIf: lint.MergeIfAny, 181 }, 182 183 "SA1015": { 184 Title: `Using \'time.Tick\' in a way that will leak. Consider using \'time.NewTicker\', and only use \'time.Tick\' in tests, commands and endless functions`, 185 Since: "2017.1", 186 Severity: lint.SeverityWarning, 187 MergeIf: lint.MergeIfAny, 188 }, 189 190 "SA1016": { 191 Title: `Trapping a signal that cannot be trapped`, 192 Text: `Not all signals can be intercepted by a process. Specifically, on 193 UNIX-like systems, the \'syscall.SIGKILL\' and \'syscall.SIGSTOP\' signals are 194 never passed to the process, but instead handled directly by the 195 kernel. It is therefore pointless to try and handle these signals.`, 196 Since: "2017.1", 197 Severity: lint.SeverityWarning, 198 MergeIf: lint.MergeIfAny, 199 }, 200 201 "SA1017": { 202 Title: `Channels used with \'os/signal.Notify\' should be buffered`, 203 Text: `The \'os/signal\' package uses non-blocking channel sends when delivering 204 signals. If the receiving end of the channel isn't ready and the 205 channel is either unbuffered or full, the signal will be dropped. To 206 avoid missing signals, the channel should be buffered and of the 207 appropriate size. For a channel used for notification of just one 208 signal value, a buffer of size 1 is sufficient.`, 209 Since: "2017.1", 210 Severity: lint.SeverityWarning, 211 MergeIf: lint.MergeIfAny, 212 }, 213 214 "SA1018": { 215 Title: `\'strings.Replace\' called with \'n == 0\', which does nothing`, 216 Text: `With \'n == 0\', zero instances will be replaced. To replace all 217 instances, use a negative number, or use \'strings.ReplaceAll\'.`, 218 Since: "2017.1", 219 Severity: lint.SeverityWarning, 220 MergeIf: lint.MergeIfAny, // MergeIfAny if we only flag literals, not named constants 221 }, 222 223 "SA1019": { 224 Title: `Using a deprecated function, variable, constant or field`, 225 Since: "2017.1", 226 Severity: lint.SeverityDeprecated, 227 MergeIf: lint.MergeIfAny, 228 }, 229 230 "SA1020": { 231 Title: `Using an invalid host:port pair with a \'net.Listen\'-related function`, 232 Since: "2017.1", 233 Severity: lint.SeverityError, 234 MergeIf: lint.MergeIfAny, 235 }, 236 237 "SA1021": { 238 Title: `Using \'bytes.Equal\' to compare two \'net.IP\'`, 239 Text: `A \'net.IP\' stores an IPv4 or IPv6 address as a slice of bytes. The 240 length of the slice for an IPv4 address, however, can be either 4 or 241 16 bytes long, using different ways of representing IPv4 addresses. In 242 order to correctly compare two \'net.IP\'s, the \'net.IP.Equal\' method should 243 be used, as it takes both representations into account.`, 244 Since: "2017.1", 245 Severity: lint.SeverityWarning, 246 MergeIf: lint.MergeIfAny, 247 }, 248 249 "SA1023": { 250 Title: `Modifying the buffer in an \'io.Writer\' implementation`, 251 Text: `\'Write\' must not modify the slice data, even temporarily.`, 252 Since: "2017.1", 253 Severity: lint.SeverityError, 254 MergeIf: lint.MergeIfAny, 255 }, 256 257 "SA1024": { 258 Title: `A string cutset contains duplicate characters`, 259 Text: `The \'strings.TrimLeft\' and \'strings.TrimRight\' functions take cutsets, not 260 prefixes. A cutset is treated as a set of characters to remove from a 261 string. For example, 262 263 strings.TrimLeft("42133word", "1234") 264 265 will result in the string \'"word"\' – any characters that are 1, 2, 3 or 266 4 are cut from the left of the string. 267 268 In order to remove one string from another, use \'strings.TrimPrefix\' instead.`, 269 Since: "2017.1", 270 Severity: lint.SeverityWarning, 271 MergeIf: lint.MergeIfAny, 272 }, 273 274 "SA1025": { 275 Title: `It is not possible to use \'(*time.Timer).Reset\''s return value correctly`, 276 Since: "2019.1", 277 Severity: lint.SeverityWarning, 278 MergeIf: lint.MergeIfAny, 279 }, 280 281 "SA1026": { 282 Title: `Cannot marshal channels or functions`, 283 Since: "2019.2", 284 Severity: lint.SeverityError, 285 MergeIf: lint.MergeIfAny, 286 }, 287 288 "SA1027": { 289 Title: `Atomic access to 64-bit variable must be 64-bit aligned`, 290 Text: `On ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to 291 arrange for 64-bit alignment of 64-bit words accessed atomically. The 292 first word in a variable or in an allocated struct, array, or slice 293 can be relied upon to be 64-bit aligned. 294 295 You can use the structlayout tool to inspect the alignment of fields 296 in a struct.`, 297 Since: "2019.2", 298 Severity: lint.SeverityWarning, 299 MergeIf: lint.MergeIfAny, 300 }, 301 302 "SA1028": { 303 Title: `\'sort.Slice\' can only be used on slices`, 304 Text: `The first argument of \'sort.Slice\' must be a slice.`, 305 Since: "2020.1", 306 Severity: lint.SeverityError, 307 MergeIf: lint.MergeIfAny, 308 }, 309 310 "SA1029": { 311 Title: `Inappropriate key in call to \'context.WithValue\'`, 312 Text: `The provided key must be comparable and should not be 313 of type \'string\' or any other built-in type to avoid collisions between 314 packages using context. Users of \'WithValue\' should define their own 315 types for keys. 316 317 To avoid allocating when assigning to an \'interface{}\', 318 context keys often have concrete type \'struct{}\'. Alternatively, 319 exported context key variables' static type should be a pointer or 320 interface.`, 321 Since: "2020.1", 322 Severity: lint.SeverityWarning, 323 MergeIf: lint.MergeIfAny, 324 }, 325 326 "SA1030": { 327 Title: `Invalid argument in call to a \'strconv\' function`, 328 Text: `This check validates the format, number base and bit size arguments of 329 the various parsing and formatting functions in \'strconv\'.`, 330 Since: "2021.1", 331 Severity: lint.SeverityError, 332 MergeIf: lint.MergeIfAny, 333 }, 334 335 "SA2000": { 336 Title: `\'sync.WaitGroup.Add\' called inside the goroutine, leading to a race condition`, 337 Since: "2017.1", 338 Severity: lint.SeverityWarning, 339 MergeIf: lint.MergeIfAny, 340 }, 341 342 "SA2001": { 343 Title: `Empty critical section, did you mean to defer the unlock?`, 344 Text: `Empty critical sections of the kind 345 346 mu.Lock() 347 mu.Unlock() 348 349 are very often a typo, and the following was intended instead: 350 351 mu.Lock() 352 defer mu.Unlock() 353 354 Do note that sometimes empty critical sections can be useful, as a 355 form of signaling to wait on another goroutine. Many times, there are 356 simpler ways of achieving the same effect. When that isn't the case, 357 the code should be amply commented to avoid confusion. Combining such 358 comments with a \'//lint:ignore\' directive can be used to suppress this 359 rare false positive.`, 360 Since: "2017.1", 361 Severity: lint.SeverityWarning, 362 MergeIf: lint.MergeIfAny, 363 }, 364 365 "SA2002": { 366 Title: `Called \'testing.T.FailNow\' or \'SkipNow\' in a goroutine, which isn't allowed`, 367 Since: "2017.1", 368 Severity: lint.SeverityError, 369 MergeIf: lint.MergeIfAny, 370 }, 371 372 "SA2003": { 373 Title: `Deferred \'Lock\' right after locking, likely meant to defer \'Unlock\' instead`, 374 Since: "2017.1", 375 Severity: lint.SeverityWarning, 376 MergeIf: lint.MergeIfAny, 377 }, 378 379 "SA3000": { 380 Title: `\'TestMain\' doesn't call \'os.Exit\', hiding test failures`, 381 Text: `Test executables (and in turn \"go test\") exit with a non-zero status 382 code if any tests failed. When specifying your own \'TestMain\' function, 383 it is your responsibility to arrange for this, by calling \'os.Exit\' with 384 the correct code. The correct code is returned by \'(*testing.M).Run\', so 385 the usual way of implementing \'TestMain\' is to end it with 386 \'os.Exit(m.Run())\'.`, 387 Since: "2017.1", 388 Severity: lint.SeverityWarning, 389 MergeIf: lint.MergeIfAny, 390 }, 391 392 "SA3001": { 393 Title: `Assigning to \'b.N\' in benchmarks distorts the results`, 394 Text: `The testing package dynamically sets \'b.N\' to improve the reliability of 395 benchmarks and uses it in computations to determine the duration of a 396 single operation. Benchmark code must not alter \'b.N\' as this would 397 falsify results.`, 398 Since: "2017.1", 399 Severity: lint.SeverityError, 400 MergeIf: lint.MergeIfAny, 401 }, 402 403 "SA4000": { 404 Title: `Binary operator has identical expressions on both sides`, 405 Since: "2017.1", 406 Severity: lint.SeverityWarning, 407 MergeIf: lint.MergeIfAny, 408 }, 409 410 "SA4001": { 411 Title: `\'&*x\' gets simplified to \'x\', it does not copy \'x\'`, 412 Since: "2017.1", 413 Severity: lint.SeverityWarning, 414 MergeIf: lint.MergeIfAny, 415 }, 416 417 "SA4003": { 418 Title: `Comparing unsigned values against negative values is pointless`, 419 Since: "2017.1", 420 Severity: lint.SeverityWarning, 421 MergeIf: lint.MergeIfAll, 422 }, 423 424 "SA4004": { 425 Title: `The loop exits unconditionally after one iteration`, 426 Since: "2017.1", 427 Severity: lint.SeverityWarning, 428 MergeIf: lint.MergeIfAll, 429 }, 430 431 "SA4005": { 432 Title: `Field assignment that will never be observed. Did you mean to use a pointer receiver?`, 433 Since: "2021.1", 434 Severity: lint.SeverityWarning, 435 MergeIf: lint.MergeIfAny, 436 }, 437 438 "SA4006": { 439 Title: `A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?`, 440 Since: "2017.1", 441 Severity: lint.SeverityWarning, 442 MergeIf: lint.MergeIfAll, 443 }, 444 445 "SA4008": { 446 Title: `The variable in the loop condition never changes, are you incrementing the wrong variable?`, 447 Since: "2017.1", 448 Severity: lint.SeverityWarning, 449 MergeIf: lint.MergeIfAll, 450 }, 451 452 "SA4009": { 453 Title: `A function argument is overwritten before its first use`, 454 Since: "2017.1", 455 Severity: lint.SeverityWarning, 456 MergeIf: lint.MergeIfAny, 457 }, 458 459 "SA4010": { 460 Title: `The result of \'append\' will never be observed anywhere`, 461 Since: "2017.1", 462 Severity: lint.SeverityWarning, 463 MergeIf: lint.MergeIfAll, 464 }, 465 466 "SA4011": { 467 Title: `Break statement with no effect. Did you mean to break out of an outer loop?`, 468 Since: "2017.1", 469 Severity: lint.SeverityWarning, 470 MergeIf: lint.MergeIfAny, 471 }, 472 473 "SA4012": { 474 Title: `Comparing a value against NaN even though no value is equal to NaN`, 475 Since: "2017.1", 476 Severity: lint.SeverityWarning, 477 MergeIf: lint.MergeIfAny, 478 }, 479 480 "SA4013": { 481 Title: `Negating a boolean twice (\'!!b\') is the same as writing \'b\'. This is either redundant, or a typo.`, 482 Since: "2017.1", 483 Severity: lint.SeverityWarning, 484 MergeIf: lint.MergeIfAny, 485 }, 486 487 "SA4014": { 488 Title: `An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either`, 489 Since: "2017.1", 490 Severity: lint.SeverityWarning, 491 MergeIf: lint.MergeIfAll, 492 }, 493 494 "SA4015": { 495 Title: `Calling functions like \'math.Ceil\' on floats converted from integers doesn't do anything useful`, 496 Since: "2017.1", 497 Severity: lint.SeverityWarning, 498 MergeIf: lint.MergeIfAll, 499 }, 500 501 "SA4016": { 502 Title: `Certain bitwise operations, such as \'x ^ 0\', do not do anything useful`, 503 Since: "2017.1", 504 Severity: lint.SeverityWarning, 505 MergeIf: lint.MergeIfAny, // MergeIfAny if we only flag literals, not named constants 506 }, 507 508 "SA4017": { 509 Title: `Discarding the return values of a function without side effects, making the call pointless`, 510 Since: "2017.1", 511 Severity: lint.SeverityWarning, 512 MergeIf: lint.MergeIfAll, 513 }, 514 515 "SA4018": { 516 Title: `Self-assignment of variables`, 517 Since: "2017.1", 518 Severity: lint.SeverityWarning, 519 MergeIf: lint.MergeIfAny, 520 }, 521 522 "SA4019": { 523 Title: `Multiple, identical build constraints in the same file`, 524 Since: "2017.1", 525 Severity: lint.SeverityWarning, 526 MergeIf: lint.MergeIfAny, 527 }, 528 529 "SA4020": { 530 Title: `Unreachable case clause in a type switch`, 531 Text: `In a type switch like the following 532 533 type T struct{} 534 func (T) Read(b []byte) (int, error) { return 0, nil } 535 536 var v interface{} = T{} 537 538 switch v.(type) { 539 case io.Reader: 540 // ... 541 case T: 542 // unreachable 543 } 544 545 the second case clause can never be reached because \'T\' implements 546 \'io.Reader\' and case clauses are evaluated in source order. 547 548 Another example: 549 550 type T struct{} 551 func (T) Read(b []byte) (int, error) { return 0, nil } 552 func (T) Close() error { return nil } 553 554 var v interface{} = T{} 555 556 switch v.(type) { 557 case io.Reader: 558 // ... 559 case io.ReadCloser: 560 // unreachable 561 } 562 563 Even though \'T\' has a \'Close\' method and thus implements \'io.ReadCloser\', 564 \'io.Reader\' will always match first. The method set of \'io.Reader\' is a 565 subset of \'io.ReadCloser\'. Thus it is impossible to match the second 566 case without matching the first case. 567 568 569 Structurally equivalent interfaces 570 571 A special case of the previous example are structurally identical 572 interfaces. Given these declarations 573 574 type T error 575 type V error 576 577 func doSomething() error { 578 err, ok := doAnotherThing() 579 if ok { 580 return T(err) 581 } 582 583 return U(err) 584 } 585 586 the following type switch will have an unreachable case clause: 587 588 switch doSomething().(type) { 589 case T: 590 // ... 591 case V: 592 // unreachable 593 } 594 595 \'T\' will always match before V because they are structurally equivalent 596 and therefore \'doSomething()\''s return value implements both.`, 597 Since: "2019.2", 598 Severity: lint.SeverityWarning, 599 MergeIf: lint.MergeIfAll, 600 }, 601 602 "SA4021": { 603 Title: `\"x = append(y)\" is equivalent to \"x = y\"`, 604 Since: "2019.2", 605 Severity: lint.SeverityWarning, 606 MergeIf: lint.MergeIfAny, 607 }, 608 609 "SA4022": { 610 Title: `Comparing the address of a variable against nil`, 611 Text: `Code such as \"if &x == nil\" is meaningless, because taking the address of a variable always yields a non-nil pointer.`, 612 Since: "2020.1", 613 Severity: lint.SeverityWarning, 614 MergeIf: lint.MergeIfAny, 615 }, 616 617 "SA4023": { 618 Title: `Impossible comparison of interface value with untyped nil`, 619 Text: `Under the covers, interfaces are implemented as two elements, a 620 type T and a value V. V is a concrete value such as an int, 621 struct or pointer, never an interface itself, and has type T. For 622 instance, if we store the int value 3 in an interface, the 623 resulting interface value has, schematically, (T=int, V=3). The 624 value V is also known as the interface's dynamic value, since a 625 given interface variable might hold different values V (and 626 corresponding types T) during the execution of the program. 627 628 An interface value is nil only if the V and T are both 629 unset, (T=nil, V is not set), In particular, a nil interface will 630 always hold a nil type. If we store a nil pointer of type *int 631 inside an interface value, the inner type will be *int regardless 632 of the value of the pointer: (T=*int, V=nil). Such an interface 633 value will therefore be non-nil even when the pointer value V 634 inside is nil. 635 636 This situation can be confusing, and arises when a nil value is 637 stored inside an interface value such as an error return: 638 639 func returnsError() error { 640 var p *MyError = nil 641 if bad() { 642 p = ErrBad 643 } 644 return p // Will always return a non-nil error. 645 } 646 647 If all goes well, the function returns a nil p, so the return 648 value is an error interface value holding (T=*MyError, V=nil). 649 This means that if the caller compares the returned error to nil, 650 it will always look as if there was an error even if nothing bad 651 happened. To return a proper nil error to the caller, the 652 function must return an explicit nil: 653 654 func returnsError() error { 655 if bad() { 656 return ErrBad 657 } 658 return nil 659 } 660 661 It's a good idea for functions that return errors always to use 662 the error type in their signature (as we did above) rather than a 663 concrete type such as \'*MyError\', to help guarantee the error is 664 created correctly. As an example, \'os.Open\' returns an error even 665 though, if not nil, it's always of concrete type *os.PathError. 666 667 Similar situations to those described here can arise whenever 668 interfaces are used. Just keep in mind that if any concrete value 669 has been stored in the interface, the interface will not be nil. 670 For more information, see The Laws of 671 Reflection (https://golang.org/doc/articles/laws_of_reflection.html). 672 673 This text has been copied from 674 https://golang.org/doc/faq#nil_error, licensed under the Creative 675 Commons Attribution 3.0 License.`, 676 Since: "2020.2", 677 Severity: lint.SeverityWarning, 678 MergeIf: lint.MergeIfAny, // TODO should this be MergeIfAll? 679 }, 680 681 "SA4024": { 682 Title: `Checking for impossible return value from a builtin function`, 683 Text: `Return values of the \'len\' and \'cap\' builtins cannot be negative. 684 685 See https://golang.org/pkg/builtin/#len and https://golang.org/pkg/builtin/#cap. 686 687 Example: 688 689 if len(slice) < 0 { 690 fmt.Println("unreachable code") 691 }`, 692 Since: "2021.1", 693 Severity: lint.SeverityWarning, 694 MergeIf: lint.MergeIfAny, 695 }, 696 697 "SA4025": { 698 Title: "Integer division of literals that results in zero", 699 Text: `When dividing two integer constants, the result will 700 also be an integer. Thus, a division such as \'2 / 3\' results in \'0\'. 701 This is true for all of the following examples: 702 703 _ = 2 / 3 704 const _ = 2 / 3 705 const _ float64 = 2 / 3 706 _ = float64(2 / 3) 707 708 Staticcheck will flag such divisions if both sides of the division are 709 integer literals, as it is highly unlikely that the division was 710 intended to truncate to zero. Staticcheck will not flag integer 711 division involving named constants, to avoid noisy positives. 712 `, 713 Since: "2021.1", 714 Severity: lint.SeverityWarning, 715 MergeIf: lint.MergeIfAny, 716 }, 717 718 "SA4026": { 719 Title: "Go constants cannot express negative zero", 720 Text: `In IEEE 754 floating point math, zero has a sign and can be positive 721 or negative. This can be useful in certain numerical code. 722 723 Go constants, however, cannot express negative zero. This means that 724 the literals \'-0.0\' and \'0.0\' have the same ideal value (zero) and 725 will both represent positive zero at runtime. 726 727 To explicitly and reliably create a negative zero, you can use the 728 \'math.Copysign\' function: \'math.Copysign(0, -1)\'.`, 729 Since: "2021.1", 730 Severity: lint.SeverityWarning, 731 MergeIf: lint.MergeIfAny, 732 }, 733 734 "SA4027": { 735 Title: `\'(*net/url.URL).Query\' returns a copy, modifying it doesn't change the URL`, 736 Text: `\'(*net/url.URL).Query\' parses the current value of \'net/url.URL.RawQuery\' 737 and returns it as a map of type \'net/url.Values\'. Subsequent changes to 738 this map will not affect the URL unless the map gets encoded and 739 assigned to the URL's \'RawQuery\'. 740 741 As a consequence, the following code pattern is an expensive no-op: 742 \'u.Query().Add(key, value)\'.`, 743 Since: "2021.1", 744 Severity: lint.SeverityWarning, 745 MergeIf: lint.MergeIfAny, 746 }, 747 748 "SA4028": { 749 Title: `\'x % 1\' is always zero`, 750 Since: "2022.1", 751 Severity: lint.SeverityWarning, 752 MergeIf: lint.MergeIfAny, // MergeIfAny if we only flag literals, not named constants 753 }, 754 755 "SA4029": { 756 Title: "Ineffective attempt at sorting slice", 757 Text: ` 758 \'sort.Float64Slice\', \'sort.IntSlice\', and \'sort.StringSlice\' are 759 types, not functions. Doing \'x = sort.StringSlice(x)\' does nothing, 760 especially not sort any values. The correct usage is 761 \'sort.Sort(sort.StringSlice(x))\' or \'sort.StringSlice(x).Sort()\', 762 but there are more convenient helpers, namely \'sort.Float64s\', 763 \'sort.Ints\', and \'sort.Strings\'. 764 `, 765 Since: "2022.1", 766 Severity: lint.SeverityWarning, 767 MergeIf: lint.MergeIfAny, 768 }, 769 770 "SA4030": { 771 Title: "Ineffective attempt at generating random number", 772 Text: ` 773 Functions in the \'math/rand\' package that accept upper limits, such 774 as \'Intn\', generate random numbers in the half-open interval [0,n). In 775 other words, the generated numbers will be \'>= 0\' and \'< n\' – they 776 don't include \'n\'. \'rand.Intn(1)\' therefore doesn't generate \'0\' 777 or \'1\', it always generates \'0\'.`, 778 Since: "2022.1", 779 Severity: lint.SeverityWarning, 780 MergeIf: lint.MergeIfAny, 781 }, 782 783 "SA4031": { 784 Title: `Checking never-nil value against nil`, 785 Since: "2022.1", 786 Severity: lint.SeverityWarning, 787 MergeIf: lint.MergeIfAny, 788 }, 789 790 "SA5000": { 791 Title: `Assignment to nil map`, 792 Since: "2017.1", 793 Severity: lint.SeverityError, 794 MergeIf: lint.MergeIfAny, 795 }, 796 797 "SA5001": { 798 Title: `Deferring \'Close\' before checking for a possible error`, 799 Since: "2017.1", 800 Severity: lint.SeverityWarning, 801 MergeIf: lint.MergeIfAny, 802 }, 803 804 "SA5002": { 805 Title: `The empty for loop (\"for {}\") spins and can block the scheduler`, 806 Since: "2017.1", 807 Severity: lint.SeverityWarning, 808 MergeIf: lint.MergeIfAny, 809 }, 810 811 "SA5003": { 812 Title: `Defers in infinite loops will never execute`, 813 Text: `Defers are scoped to the surrounding function, not the surrounding 814 block. In a function that never returns, i.e. one containing an 815 infinite loop, defers will never execute.`, 816 Since: "2017.1", 817 Severity: lint.SeverityWarning, 818 MergeIf: lint.MergeIfAny, 819 }, 820 821 "SA5004": { 822 Title: `\"for { select { ...\" with an empty default branch spins`, 823 Since: "2017.1", 824 Severity: lint.SeverityWarning, 825 MergeIf: lint.MergeIfAny, 826 }, 827 828 "SA5005": { 829 Title: `The finalizer references the finalized object, preventing garbage collection`, 830 Text: `A finalizer is a function associated with an object that runs when the 831 garbage collector is ready to collect said object, that is when the 832 object is no longer referenced by anything. 833 834 If the finalizer references the object, however, it will always remain 835 as the final reference to that object, preventing the garbage 836 collector from collecting the object. The finalizer will never run, 837 and the object will never be collected, leading to a memory leak. That 838 is why the finalizer should instead use its first argument to operate 839 on the object. That way, the number of references can temporarily go 840 to zero before the object is being passed to the finalizer.`, 841 Since: "2017.1", 842 Severity: lint.SeverityWarning, 843 MergeIf: lint.MergeIfAny, 844 }, 845 846 "SA5007": { 847 Title: `Infinite recursive call`, 848 Text: `A function that calls itself recursively needs to have an exit 849 condition. Otherwise it will recurse forever, until the system runs 850 out of memory. 851 852 This issue can be caused by simple bugs such as forgetting to add an 853 exit condition. It can also happen "on purpose". Some languages have 854 tail call optimization which makes certain infinite recursive calls 855 safe to use. Go, however, does not implement TCO, and as such a loop 856 should be used instead.`, 857 Since: "2017.1", 858 Severity: lint.SeverityWarning, 859 MergeIf: lint.MergeIfAny, 860 }, 861 862 "SA5008": { 863 Title: `Invalid struct tag`, 864 Since: "2019.2", 865 Severity: lint.SeverityWarning, 866 MergeIf: lint.MergeIfAny, 867 }, 868 869 "SA5009": { 870 Title: `Invalid Printf call`, 871 Since: "2019.2", 872 Severity: lint.SeverityError, 873 MergeIf: lint.MergeIfAny, 874 }, 875 876 "SA5010": { 877 Title: `Impossible type assertion`, 878 879 Text: `Some type assertions can be statically proven to be 880 impossible. This is the case when the method sets of both 881 arguments of the type assertion conflict with each other, for 882 example by containing the same method with different 883 signatures. 884 885 The Go compiler already applies this check when asserting from an 886 interface value to a concrete type. If the concrete type misses 887 methods from the interface, or if function signatures don't match, 888 then the type assertion can never succeed. 889 890 This check applies the same logic when asserting from one interface to 891 another. If both interface types contain the same method but with 892 different signatures, then the type assertion can never succeed, 893 either.`, 894 895 Since: "2020.1", 896 Severity: lint.SeverityWarning, 897 // Technically this should be MergeIfAll, but the Go compiler 898 // already flags some impossible type assertions, so 899 // MergeIfAny is consistent with the compiler. 900 MergeIf: lint.MergeIfAny, 901 }, 902 903 "SA5011": { 904 Title: `Possible nil pointer dereference`, 905 906 Text: `A pointer is being dereferenced unconditionally, while 907 also being checked against nil in another place. This suggests that 908 the pointer may be nil and dereferencing it may panic. This is 909 commonly a result of improperly ordered code or missing return 910 statements. Consider the following examples: 911 912 func fn(x *int) { 913 fmt.Println(*x) 914 915 // This nil check is equally important for the previous dereference 916 if x != nil { 917 foo(*x) 918 } 919 } 920 921 func TestFoo(t *testing.T) { 922 x := compute() 923 if x == nil { 924 t.Errorf("nil pointer received") 925 } 926 927 // t.Errorf does not abort the test, so if x is nil, the next line will panic. 928 foo(*x) 929 } 930 931 Staticcheck tries to deduce which functions abort control flow. 932 For example, it is aware that a function will not continue 933 execution after a call to \'panic\' or \'log.Fatal\'. However, sometimes 934 this detection fails, in particular in the presence of 935 conditionals. Consider the following example: 936 937 func Log(msg string, level int) { 938 fmt.Println(msg) 939 if level == levelFatal { 940 os.Exit(1) 941 } 942 } 943 944 func Fatal(msg string) { 945 Log(msg, levelFatal) 946 } 947 948 func fn(x *int) { 949 if x == nil { 950 Fatal("unexpected nil pointer") 951 } 952 fmt.Println(*x) 953 } 954 955 Staticcheck will flag the dereference of \'x\', even though it is perfectly 956 safe. Staticcheck is not able to deduce that a call to 957 Fatal will exit the program. For the time being, the easiest 958 workaround is to modify the definition of Fatal like so: 959 960 func Fatal(msg string) { 961 Log(msg, levelFatal) 962 panic("unreachable") 963 } 964 965 We also hard-code functions from common logging packages such as 966 logrus. Please file an issue if we're missing support for a 967 popular package.`, 968 Since: "2020.1", 969 Severity: lint.SeverityWarning, 970 MergeIf: lint.MergeIfAny, 971 }, 972 973 "SA5012": { 974 Title: "Passing odd-sized slice to function expecting even size", 975 Text: `Some functions that take slices as parameters expect the slices to have an even number of elements. 976 Often, these functions treat elements in a slice as pairs. 977 For example, \'strings.NewReplacer\' takes pairs of old and new strings, 978 and calling it with an odd number of elements would be an error.`, 979 Since: "2020.2", 980 Severity: lint.SeverityError, 981 MergeIf: lint.MergeIfAny, 982 }, 983 984 "SA6000": { 985 Title: `Using \'regexp.Match\' or related in a loop, should use \'regexp.Compile\'`, 986 Since: "2017.1", 987 Severity: lint.SeverityWarning, 988 MergeIf: lint.MergeIfAny, 989 }, 990 991 "SA6001": { 992 Title: `Missing an optimization opportunity when indexing maps by byte slices`, 993 994 Text: `Map keys must be comparable, which precludes the use of byte slices. 995 This usually leads to using string keys and converting byte slices to 996 strings. 997 998 Normally, a conversion of a byte slice to a string needs to copy the data and 999 causes allocations. The compiler, however, recognizes \'m[string(b)]\' and 1000 uses the data of \'b\' directly, without copying it, because it knows that 1001 the data can't change during the map lookup. This leads to the 1002 counter-intuitive situation that 1003 1004 k := string(b) 1005 println(m[k]) 1006 println(m[k]) 1007 1008 will be less efficient than 1009 1010 println(m[string(b)]) 1011 println(m[string(b)]) 1012 1013 because the first version needs to copy and allocate, while the second 1014 one does not. 1015 1016 For some history on this optimization, check out commit 1017 f5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.`, 1018 Since: "2017.1", 1019 Severity: lint.SeverityWarning, 1020 MergeIf: lint.MergeIfAny, 1021 }, 1022 1023 "SA6002": { 1024 Title: `Storing non-pointer values in \'sync.Pool\' allocates memory`, 1025 Text: `A \'sync.Pool\' is used to avoid unnecessary allocations and reduce the 1026 amount of work the garbage collector has to do. 1027 1028 When passing a value that is not a pointer to a function that accepts 1029 an interface, the value needs to be placed on the heap, which means an 1030 additional allocation. Slices are a common thing to put in sync.Pools, 1031 and they're structs with 3 fields (length, capacity, and a pointer to 1032 an array). In order to avoid the extra allocation, one should store a 1033 pointer to the slice instead. 1034 1035 See the comments on https://go-review.googlesource.com/c/go/+/24371 1036 that discuss this problem.`, 1037 Since: "2017.1", 1038 Severity: lint.SeverityWarning, 1039 MergeIf: lint.MergeIfAny, 1040 }, 1041 1042 "SA6003": { 1043 Title: `Converting a string to a slice of runes before ranging over it`, 1044 Text: `You may want to loop over the runes in a string. Instead of converting 1045 the string to a slice of runes and looping over that, you can loop 1046 over the string itself. That is, 1047 1048 for _, r := range s {} 1049 1050 and 1051 1052 for _, r := range []rune(s) {} 1053 1054 will yield the same values. The first version, however, will be faster 1055 and avoid unnecessary memory allocations. 1056 1057 Do note that if you are interested in the indices, ranging over a 1058 string and over a slice of runes will yield different indices. The 1059 first one yields byte offsets, while the second one yields indices in 1060 the slice of runes.`, 1061 Since: "2017.1", 1062 Severity: lint.SeverityWarning, 1063 MergeIf: lint.MergeIfAny, 1064 }, 1065 1066 "SA6005": { 1067 Title: `Inefficient string comparison with \'strings.ToLower\' or \'strings.ToUpper\'`, 1068 Text: `Converting two strings to the same case and comparing them like so 1069 1070 if strings.ToLower(s1) == strings.ToLower(s2) { 1071 ... 1072 } 1073 1074 is significantly more expensive than comparing them with 1075 \'strings.EqualFold(s1, s2)\'. This is due to memory usage as well as 1076 computational complexity. 1077 1078 \'strings.ToLower\' will have to allocate memory for the new strings, as 1079 well as convert both strings fully, even if they differ on the very 1080 first byte. strings.EqualFold, on the other hand, compares the strings 1081 one character at a time. It doesn't need to create two intermediate 1082 strings and can return as soon as the first non-matching character has 1083 been found. 1084 1085 For a more in-depth explanation of this issue, see 1086 https://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/`, 1087 Since: "2019.2", 1088 Severity: lint.SeverityWarning, 1089 MergeIf: lint.MergeIfAny, 1090 }, 1091 1092 "SA9001": { 1093 Title: `Defers in range loops may not run when you expect them to`, 1094 Since: "2017.1", 1095 Severity: lint.SeverityWarning, 1096 MergeIf: lint.MergeIfAny, 1097 }, 1098 1099 "SA9002": { 1100 Title: `Using a non-octal \'os.FileMode\' that looks like it was meant to be in octal.`, 1101 Since: "2017.1", 1102 Severity: lint.SeverityWarning, 1103 MergeIf: lint.MergeIfAny, 1104 }, 1105 1106 "SA9003": { 1107 Title: `Empty body in an if or else branch`, 1108 Since: "2017.1", 1109 Severity: lint.SeverityWarning, 1110 MergeIf: lint.MergeIfAny, 1111 }, 1112 1113 "SA9004": { 1114 Title: `Only the first constant has an explicit type`, 1115 1116 Text: `In a constant declaration such as the following: 1117 1118 const ( 1119 First byte = 1 1120 Second = 2 1121 ) 1122 1123 the constant Second does not have the same type as the constant First. 1124 This construct shouldn't be confused with 1125 1126 const ( 1127 First byte = iota 1128 Second 1129 ) 1130 1131 where \'First\' and \'Second\' do indeed have the same type. The type is only 1132 passed on when no explicit value is assigned to the constant. 1133 1134 When declaring enumerations with explicit values it is therefore 1135 important not to write 1136 1137 const ( 1138 EnumFirst EnumType = 1 1139 EnumSecond = 2 1140 EnumThird = 3 1141 ) 1142 1143 This discrepancy in types can cause various confusing behaviors and 1144 bugs. 1145 1146 1147 Wrong type in variable declarations 1148 1149 The most obvious issue with such incorrect enumerations expresses 1150 itself as a compile error: 1151 1152 package pkg 1153 1154 const ( 1155 EnumFirst uint8 = 1 1156 EnumSecond = 2 1157 ) 1158 1159 func fn(useFirst bool) { 1160 x := EnumSecond 1161 if useFirst { 1162 x = EnumFirst 1163 } 1164 } 1165 1166 fails to compile with 1167 1168 ./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment 1169 1170 1171 Losing method sets 1172 1173 A more subtle issue occurs with types that have methods and optional 1174 interfaces. Consider the following: 1175 1176 package main 1177 1178 import "fmt" 1179 1180 type Enum int 1181 1182 func (e Enum) String() string { 1183 return "an enum" 1184 } 1185 1186 const ( 1187 EnumFirst Enum = 1 1188 EnumSecond = 2 1189 ) 1190 1191 func main() { 1192 fmt.Println(EnumFirst) 1193 fmt.Println(EnumSecond) 1194 } 1195 1196 This code will output 1197 1198 an enum 1199 2 1200 1201 as \'EnumSecond\' has no explicit type, and thus defaults to \'int\'.`, 1202 Since: "2019.1", 1203 Severity: lint.SeverityWarning, 1204 MergeIf: lint.MergeIfAny, 1205 }, 1206 1207 "SA9005": { 1208 Title: `Trying to marshal a struct with no public fields nor custom marshaling`, 1209 Text: ` 1210 The \'encoding/json\' and \'encoding/xml\' packages only operate on exported 1211 fields in structs, not unexported ones. It is usually an error to try 1212 to (un)marshal structs that only consist of unexported fields. 1213 1214 This check will not flag calls involving types that define custom 1215 marshaling behavior, e.g. via \'MarshalJSON\' methods. It will also not 1216 flag empty structs.`, 1217 Since: "2019.2", 1218 Severity: lint.SeverityWarning, 1219 MergeIf: lint.MergeIfAll, 1220 }, 1221 1222 "SA9006": { 1223 Title: `Dubious bit shifting of a fixed size integer value`, 1224 Text: `Bit shifting a value past its size will always clear the value. 1225 1226 For instance: 1227 1228 v := int8(42) 1229 v >>= 8 1230 1231 will always result in 0. 1232 1233 This check flags bit shifting operations on fixed size integer values only. 1234 That is, int, uint and uintptr are never flagged to avoid potential false 1235 positives in somewhat exotic but valid bit twiddling tricks: 1236 1237 // Clear any value above 32 bits if integers are more than 32 bits. 1238 func f(i int) int { 1239 v := i >> 32 1240 v = v << 32 1241 return i-v 1242 }`, 1243 Since: "2020.2", 1244 Severity: lint.SeverityWarning, 1245 // Technically this should be MergeIfAll, because the type of 1246 // v might be different for different build tags. Practically, 1247 // don't write code that depends on that. 1248 MergeIf: lint.MergeIfAny, 1249 }, 1250 1251 "SA9007": { 1252 Title: "Deleting a directory that shouldn't be deleted", 1253 Text: ` 1254 It is virtually never correct to delete system directories such as 1255 /tmp or the user's home directory. However, it can be fairly easy to 1256 do by mistake, for example by mistakingly using \'os.TempDir\' instead 1257 of \'ioutil.TempDir\', or by forgetting to add a suffix to the result 1258 of \'os.UserHomeDir\'. 1259 1260 Writing 1261 1262 d := os.TempDir() 1263 defer os.RemoveAll(d) 1264 1265 in your unit tests will have a devastating effect on the stability of your system. 1266 1267 This check flags attempts at deleting the following directories: 1268 1269 - os.TempDir 1270 - os.UserCacheDir 1271 - os.UserConfigDir 1272 - os.UserHomeDir 1273 `, 1274 Since: "2022.1", 1275 Severity: lint.SeverityWarning, 1276 MergeIf: lint.MergeIfAny, 1277 }, 1278 1279 "SA9008": { 1280 Title: `\'else\' branch of a type assertion is probably not reading the right value`, 1281 Text: ` 1282 When declaring variables as part of an \'if\' statement (like in \"if 1283 foo := ...; foo {\"), the same variables will also be in the scope of 1284 the \'else\' branch. This means that in the following example 1285 1286 if x, ok := x.(int); ok { 1287 // ... 1288 } else { 1289 fmt.Printf("unexpected type %T", x) 1290 } 1291 1292 \'x\' in the \'else\' branch will refer to the \'x\' from \'x, ok 1293 :=\'; it will not refer to the \'x\' that is being type-asserted. The 1294 result of a failed type assertion is the zero value of the type that 1295 is being asserted to, so \'x\' in the else branch will always have the 1296 value \'0\' and the type \'int\'. 1297 `, 1298 Since: "2022.1", 1299 Severity: lint.SeverityWarning, 1300 MergeIf: lint.MergeIfAny, 1301 }, 1302 })