// HACKER NEWS — CYBERSECURITY
How Go detects struct copies with sync.noCopy
If you have read the source code of the sync package, you may have noticed that several structs contain an unusual field of type noCopy, such as sync.Mutex, sync.Once, and sync.Map:
noCopy is a special marker for types that must not be copied after their first use. But the marker itself is only an empty struct with two empty methods:
Despite the method names, there is no lock and nothing gets unlocked. But nothing here stops us from copying the value. This post explains what can break after a copy, why noCopy needs these two methods, and how to add the same marker to your own types.
The noCopy marker does not add any special rule to the Go compiler. You can still copy a sync.Map after it has been used:
The assignment copies all the fields from a into b, exactly as it would for any other struct value. The code still passes go build because the compiler gives no special meaning to the name noCopy or to its Lock and Unlock methods.
It turns out that the warning comes from a separate tool called go vet. This static-analysis command is included with Go and reports suspicious code that the compiler still accepts. When go vet checks the same assignment, it reports:
The phrase copies lock value comes from the purpose of the copylocks checker in go vet. It was created to report copies of values that contain a lock, such as sync.Mutex, because copying a lock after it has been used also copies its internal state.
The behavior is easy to reproduce with a regular struct that contains sync.Mutex:
Counter contains an actual mutex, so copying the outer struct also copies the mutex state.
So go vet produces this warning through its copylocks checker and this checker does not search for a field named noCopy. It uses the following rule while inspecting the copied type and its fields: