Понимание приемников указателей и копирования экземпляров
В 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