ELSEIF
Your brief EB
339 stories from 110 feeds 376 clusters Refreshed 7 minutes ago next pull 21:22

TECH Signal 522 2 feeds carried it

go vet's copylocks checker flags sync.noCopy via sync.Locker interface, not the compiler

Go detects copies of noCopy-marked structs in the go vet copylocks analyzer, which flags any type whose pointer implements sync.Locker while its value type does not.

WHY IT MATTERS

Engineers who want to mark their own types as non-copyable need only add an empty `Lock()` and `Unlock()` method pair on a pointer receiver; the Go compiler itself performs no check, so the warning only surfaces in workflows that run `go vet` (directly, through `go test`, or via CI linting). The standard library's use of explicit `_ noCopy` fields alongside internal mutexes is a deliberate decoupling so that refactoring internals does not silently break the check and so the warning text names the marker rather than an implementation detail.

Written by elseif from the cluster below · every claim links back to a source

The three things worth knowing

01

The `noCopy` warning is not produced by the Go compiler but by the `copylocks` analyzer inside `go vet`; `go build` accepts the copy.

02

The checker flags a type when its pointer satisfies `sync.Locker` (both `Lock` and `Unlock`) while its value type does not, which is why `noCopy` declares those methods on a pointer receiver.

03

Standard library types like `sync.Map`, `sync.Once`, and `sync.Mutex` carry an explicit `_ noCopy` field in addition to any internal mutex so the warning decouples from internal state and reports a clearer message.

THE READ

What the cluster adds up to.

ORIGINAL ANALYSIS

The article is a deep dive into a Go behavior that is invisible to most engineers: a `_ noCopy` field inside `sync.Mutex`, `sync.Once`, and `sync.Map` causes a warning when those values are copied, yet the field is just an empty struct with two empty methods. The first thing the piece establishes is that this is not a compiler feature. The Go compiler treats `noCopy` like any other empty struct, and code that copies a `sync.Map` after use still passes `go build`. The detection lives in `go vet`, specifically its `copylocks` static analyzer, which is a separate tool that runs alongside the compiler. This means the protection is conditional on whether `go vet` is part of the engineer's local loop or CI pipeline at all.

The `copylocks` analyzer does not look for a field literally named `noCopy`. It tests whether the type's pointer implements `sync.Locker` (the interface with `Lock()` and `Unlock()` methods) while the value type does not, and walks the type recursively into fields. `noCopy` is defined as an empty struct whose `Lock()` and `Unlock()` methods are declared on a pointer receiver, which makes `*noCopy` satisfy the interface while the value type does not. The article notes this was a deliberate evolution: the original 2016 marker had only `Lock()`, and `Unlock()` was added in 2018 when `copylocks` switched to checking the full `sync.Locker` interface. Any custom type wanting the same protection needs both methods on a pointer receiver, and a missing one makes the type invisible to the checker.

A natural question the article answers is why `sync.Map` carries both an embedded `sync.Mutex` and an explicit `_ noCopy` field, since `copylocks` could already reach the mutex. Three reasons are given. First, the explicit marker decouples the warning from how the struct is implemented, so internal refactors cannot silently break the check. Second, the warning text becomes more useful to a caller: it reads `contains sync.noCopy` rather than naming an internal mutex that outside code should not depend on. Third, there is a false-negative case the marker resolves where a wrapping struct's own pointer-vs-value relationship does not cleanly match the rule but an inner `noCopy` field gives the checker a direct hit.

The mechanism has a clear ceiling. Because detection is in `go vet` and not the compiler or runtime, code that compiles and runs without `go vet` being invoked will silently copy noCopy-marked values, with all the concurrency hazards that implies. The check is also purely static, so reflection, code generation, or `unsafe` pointer manipulation can subvert it without producing any warning. For a working engineer, the practical implication is that adding `_ noCopy` to a struct is only protective when every developer and CI run actually executes `go vet`, or a linter using the same analyzer, on that code path.

Written by elseif from the cluster below · checked for specifics the sources never contained

THE CLUSTER

Same story, 2 feeds.

ORDERED BY FIRST SEEN
func25.dev via Hacker News How Go detects struct copies with sync.noCopy Open ↗
func25.dev via Lobsters How Go detects struct copies with sync.noCopy Open ↗