«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > ## Почему я не могу просто скопировать экземпляры типов с приемниками указателей в Go?

## Почему я не могу просто скопировать экземпляры типов с приемниками указателей в Go?

Опубликовано 8 ноября 2024 г.
Просматривать:892

## Why Can\'t I Just Copy Instances of Types With Pointer Receivers in Go?

Понимание приемников указателей и копирования экземпляров

В Go метод может быть определен либо с помощью получателя значения, либо с приемником указателя. Когда все методы типа T имеют тип-получатель самого T, безопасно копировать экземпляры этого типа, поскольку вызов любого из его методов обязательно создает копию.

Однако ситуация меняется, когда тип имеет методы с приемником указателя. В этом случае следует избегать копирования экземпляров этого типа, так как это может нарушить внутренние инварианты.

Проблема с копированием указателей

Давайте рассмотрим пример, иллюстрирующий проблема. Предположим, у нас есть тип Wrapper с двумя полями: значением v и указателем p. Мы намерены хранить одно и то же число как в v, так и в указанном значении p. Чтобы обеспечить это, мы предоставляем метод Set с приемником указателя:

type Wrapper struct {
    v int
    p *int
}

func (w *Wrapper) Set(v int) {
    w.v = v
    *w.p = v
}

Если у нас есть экземпляр Wrapper и мы вызываем метод Set, он изменит указанное значение p. Однако если мы создадим копию экземпляра, эта копия будет иметь то же значение указателя p, что и исходный экземпляр. Это означает, что любые последующие вызовы метода в любом экземпляре повлияют на обе копии.

Пример:

a := Wrapper{v: 0, p: new(int)}
b := a

fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

a.Set(1)
fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

Вывод:

a.v=0, a.p=0;  b.v=0, b.p=0
a.v=1, a.p=1;  b.v=0, b.p=1

В этом примере значение b становится недействительным после вызова a.Set(1), поскольку b.v не равно *b.p. Это связано с тем, что указатель p как в a, так и в b указывает на одно и то же базовое значение.

Чтобы избежать таких проблем, рекомендуется работать со значениями указателя при использовании методов с получателями указателей. В качестве альтернативы, если тип может иметь только получатели значений, можно безопасно копировать экземпляры этого типа независимо от вызовов методов.

Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3