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 :
go type Mutex struct { _ noCopy ... } type Once struct { _ noCopy ... } type Map struct { _ noCopy ... }
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:
go type noCopy struct {} func ( * noCopy ) Lock () {} func ( * noCopy ) Unlock () {}
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.
1. What noCopy does and does not do
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:
go var a sync . Map a . Store ( "k" , 1 ) b := a // copying a sync.Map
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:
... continue reading