Как клонировать структуру с неэкспортированным полем?
Если у меня есть тип, определенный как:
type T struct {
S string
is []int
}
тогда как я могу пойти клонировать объект этого типа? Если я делаю простое задание:
p := T{"some string", []int{10, 20}}
q := p
Затем любые изменения, внесенные в []int
влияет на оба объекта. поскольку T.is
не экспортируется, его нельзя скопировать явно, даже если он извлечен с использованием отражения.
В настоящее время я поставляю Clone
Метод в пакете самого типа. Но это не помогает с подобными типами в других пакетах. Есть ли другой способ сделать это?
1 ответ
Ты не можешь В этом суть неэкспортированных полей: только декларирующий пакет может их изменить.
Обратите внимание, что если T
тип объявлен в другом пакете, вы даже не можете написать:
p := somepackage.T{"some string", []int{10, 20}}
потому что это будет неявно пытаться установить необъявленное T.is
поле и, следовательно, приводит к ошибке времени компиляции:
implicit assignment of unexported field 'is' in somepackage.T literal
Если вы являетесь владельцем (или можете изменить) пакета, лучше всего предоставить Clone()
метод или функцию, или предоставить SetIs()
метод для типа T
, Если сторонний пакет не предоставляет такую функциональность, вы ничего не можете с этим поделать.
Обратите внимание, что с помощью пакетаunsafe
можно делать такие вещи, но как следует из названия: это небезопасно, и вы должны держаться подальше от этого.
Также обратите внимание, что вы можете создавать новые значения T
где is
не копируется, но будет нулевым значением своего типа (которое в случае []int
будет nil
):
var r somepackage.T
s := somepackage.T{S: p.S}
fmt.Printf("%q\n", r)
fmt.Printf("%q\n", s)
Который будет выводить:
{"" []}
{"some string" []}
Но вы не можете установить ненулевое значение для неэкспортированного поля T.is
,