---
title: Staticcheck 2024.1 release notes
linkTitle: "2024.1 (v0.5.0)"
weight: -9
---

## Backwards incompatible changes

Staticcheck 2024.1 contains the following backwards incompatible changes:

- The `keyify` utility has been removed. The recommended alternative is gopls.
- `staticcheck -merge` now exits with a non-zero status if any problems have
  been found.

## Improved Go 1.22 support

This release updates Staticcheck's database of deprecated standard library APIs
to cover the Go 1.22 release. Furthermore, checks have been updated to correctly
handle the new "for" loop variable scoping behavior as well as ranging over
integers.

## Added Go 1.23 support

Staticcheck 2024.1 has full support for iterators / range-over-func.
Furthermore, {{< check "SA1015" >}} will skip any code targeting Go 1.23 or
newer, as it is now possible to use `time.Tick` without leaking memory.

## Improved handling of Go versions

Go 1.21 more rigorously defined the meaning of the `go` directive in `go.mod`
files, as well as its interactions with `//go:build go1.N` build constraints.
The `go` directive now specifies a _minimum_ Go version for the module.
Furthermore, it sets the language version that is in effect, which may change
the semantics of Go code. For example, before Go 1.22, loop variables were
reused across iterations, but since Go 1.22, loop variables only exist for the
duration of an iteration. Modules that specify `go 1.22` will use the new
semantics, while modules that specify an older version will not.

Individual files can both upgrade and downgrade their language version by using
`//go:build go1.N` directives. In a module that requires Go 1.22, a file
specifying Go 1.21 will experience the old loop variable semantics, and vice
versa. Because the Go module as a whole still specifies a minimum version, even
files specifying an older version will have access to the standard library of
the minimum version.

Staticcheck 2024.1 takes all of this into consideration when analyzing the
behavior of Go code, when determining which checks are applicable, and when
making suggestions. Older versions of Staticcheck were already aware of Go
versions, but 2024.1 works on a more fine-grained, per-file basis, and
differentiates between the pre- and post-1.21 semantics of the `go` directive.

The `-go` command line flag continues to exist. It will override any
module-based version selection. This is primarily useful for Go modules that
target older Go versions (because here, the `go` directive didn't specify a
_minimum_ version), or when working outside of Go modules.

To prevent misinterpreting code, Staticcheck now refuses to analyze modules that
require a version of Go that is newer than that with which Staticcheck was
built.

## Checks

### New checks

The following checks have been added:

- {{< check "SA1031" >}} flags overlapping destination and source slices passed
  to certain encoding functions.
- {{< check "SA1032" >}} flags calls to
  [`errors.Is`](https://pkg.go.dev/errors#Is) where the two arguments have been
  swapped.
- {{< check "SA4032" >}} flags impossible comparisons of
  [runtime.GOOS](https://pkg.go.dev/runtime#GOOS) and
  [runtime.GOARCH](https://pkg.go.dev/runtime#GOARCH) based on the file's build
  tags.
- {{< check "SA6006" >}} flags `io.WriteString(w, string(b))` as it would be
  both simpler and more efficient to use `w.Write(b)`.
- {{< check "SA9009" >}} flags comments that look like they intend to be
  compiler directives but which aren't due to extraneous whitespace.

### Changed checks

The following checks have been improved:

- {{< check "QF1001" >}} no longer panics on expressions involving "key: value"
  pairs ({{< issue "1484" >}}).
- {{< check "S1008" >}} now understands that some built-in functions never
  return negative values. For example, it now negates `len(x) > 0` as `len(x) ==
  0` ({{< issue "1422" >}}).
- {{< check "S1009" >}} now flags unnecessary nil checks that involve selector
  expressions ({{< issue "1527" >}}).
- {{< check "S1017" >}} no longer flags `if else` branches ({{< issue "1447"
  >}}).
- {{< check "SA1006" >}} now detects more Printf-like functions from the
  standard library ({{< issue "1528" >}}).
- {{< check "SA1015" >}} now skips any code targeting Go 1.23 or newer ({{<
  issue "1558" >}}).
- {{< check "SA1029" >}} now flags uses of the empty struct (`struct{}`) as
  context keys ({{< issue "1504" >}}).
- {{< check "SA4003" >}} now flags pointless integer comparisons that involve
  literals, not just constants from the `math` package ({{< issue "1470" >}}).
- {{< check "SA4015" >}} now supports conversions that involve generics.
- {{< check "SA4023" >}} no longer panics on type sets that contain arrays ({{<
  issue "1397" >}}).
- {{< check "SA5001" >}} now emits a clearer message ({{< issue "1489" >}}).
- {{< check "SA9003" >}} has been disabled by default because of too many noisy
  positives ({{< issue "321" >}}).
- {{< check "ST1000" >}} now permits punctuation following the package name, as
  in "Package pkg, which ..." ({{< issue "1452" >}}).
- {{< check "ST1018" >}} now accepts variation selectors in emoji and certain
  Arabic formatting characters in string literals ({{< issue "1456" >}}).
- {{< check "ST1020" >}} no longer flags comments that start with a deprecation
  notice ({{< issue "1378" >}}).
- {{< check "U1000" >}} handles generic interfaces slightly better, reducing the
  number of false positives.
- Due to improvements in the intermediate representation, various checks may now
  detect more problems.

## Miscellaneous changes and fixes

- The `keyify` utility has been deleted. This functionality is provided by gopls
  nowadays.
- `staticcheck -merge` now exits with a non-zero exit status if any problems
  were found. This matches the behavior of non-merge uses.
- Malformed `staticcheck.conf` files now cause more useful errors to be emitted.
- Labeled statements with blank labels no longer cause panics.
- Functions with named return parameters that never actually return no longer
  cause panics ({{< issue "1533" >}}).
