Nocopy минимальный пример?
Я пытался получить noCopy
директива работать на одну из моих собственных структур, но я не могу получить go vet
обнаружить это.
Я могу получить это, чтобы обнаружить копирование sync.WaitGroup
, а также sync.Mutex
, но не моя собственная структура. Этот тестовый файл в ветеринарном источнике даже не запускается с моим go vet
,
Или хорошо, он находит некоторые из ошибок:
# command-line-arguments
./govet.go:56:6: no new variables on left side of :=
./govet.go:110:17: unsafe.Sizeof(mu) evaluated but not used
./govet.go:111:18: unsafe.Sizeof(mu) evaluated but not used
./govet.go:112:10: unsafe.Sizeof(mu) evaluated but not used
но обнаружение копирования не находит ничего.
Что-то изменилось в go vet
так как это обсуждение на 1.4? я бегу go version go1.11 darwin/amd64
,
1 ответ
Во-первых, копирование блокировок правильно определяется go vet
, Пример:
type My struct {
l sync.Mutex
}
Использование:
func main() {
m := My{}
m2 := m
fmt.Println(m2)
}
Бег go vet
, вывод:
./play.go:25: assignment copies lock value to m2: main.My contains sync.Mutex
./play.go:26: call of fmt.Println copies lock value: main.My contains sync.Mutex
Таким образом, оба случая (назначение и передача fmt.Println()
) были обнаружены.
Это также означает, что самый простой способ сделать вашу структуру целью ветеринара при копировании, просто добавив поле типа sync.Mutex
, Это готовое решение, хотя и потребляет память (sync.Mutex
не является структурой нулевого размера). Неважно, используете ли вы этот мьютекс или нет (мы не использовали его в приведенном выше примере).
В обсуждении, на которое вы ссылались, Роб Пайк предлагает создать тип:
type noCopy struct{}
func (*noCopy) Lock() {}
И используйте поле этого типа (обычное или встроенное), чтобы пометить структуру как не копируемую (и таким образом сделать go vet
кричать, если это произойдет).
Я не знаю, работало ли это когда-либо, но в настоящее время это не работает, потому что go vet
проверяет на sync.Locker
интерфейс, который также имеет Unlock()
метод:
type Locker interface {
Lock()
Unlock()
}
Так что, если мы создадим noCopy
тип, который реализует sync.Locker
(точнее его тип указателя), который будет работать:
type noCopy struct{}
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
type By struct {
noCopy noCopy
}
Тестирование это:
func main() {
b := By{}
b2 := b
fmt.Println(b2)
}
Бег go vet
:
./play.go:29: assignment copies lock value to b2: main.By contains main.noCopy
./play.go:30: call of fmt.Println copies lock value: main.By contains main.noCopy
Вот некоторые изменения, связанные с go vet
а также noCopy
: