Как клонировать структуру с неэкспортированным полем?

Если у меня есть тип, определенный как:

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,

Другие вопросы по тегам