How Go's vet catches copies of sync.Mutex and noCopy

How Go detects struct copies with sync.noCopy

How Go's vet catches copies of sync.Mutex and noCopy

Go's sync package uses a zero-size noCopy marker to prevent copying types like sync.Mutex and sync.Map. The marker works with go vet's copylocks checker, which flags copies of types that implement sync.Locker only via pointer. The checker recursively inspects struct fields, so even types that embed noCopy indirectly are caught. This article explains the mechanism, why noCopy has Lock and Unlock methods, and how to add the marker to your own types. It also covers edge cases like sync.RWMutex and the impact of field placement on struct size.

The marker still cannot stop the compiler from copying a value.
  1. meerita

    I spoke with Aliaksandr Valialkin (author of noCopy) and he gave me his reasons:

    - https://x.com/valyala/status/2088638160242683954

    He also gave an answer of what he would change now: https://itnext.io/go-evolves-in-the-wrong-direction-7dfda8a1...

    It seems he's not happy anymore with the new direction of Go because they're implementing things from other languages.

  2. woadwarrior01

    > noCopy is a special marker for types that must not be copied after their first use.

    if it looks like a hack, walks like a hack, and quacks like a hack...

  3. CamouflagedKiwi

    This feels like it should ideally be something public in the structs package so anyone can leverage it, not just a specially blessed internal thing for the sync package.

  4. fithisux

    Very good article. Interesting approach working in harmony with `go vet`.

More from this day

2026-08-17