Nocopy минимальный пример? - PullRequest
       15

Nocopy минимальный пример?

0 голосов
/ 25 сентября 2018

Я пытался заставить директиву 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 Ответ

0 голосов
/ 25 сентября 2018

Во-первых, блокировка копирования правильно обнаружена 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:

Go 1.7

Go 1.8

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...