Я хочу создать структуру, которая будет доступна в других пакетах, но я не хочу разрешать изменять эту структуру. На других языках это архивируется, делая все поля приватными и выставляя только открытые получатели.
Решение с геттерами прекрасно работает для всех типов данных, кроме срезов и карт, поскольку возвращаемые срезы и карты не копируются по умолчанию, поэтому их можно изменять. Единственное решение, которое мне удалось выяснить, - это создать новую карту / фрагмент и назначить все элементы в цикле, но это вводит много повторяющегося и уродливого кода, особенно для больших вложенных структур.
package main
import (
"fmt"
)
type OtherStruct struct {
prop string
}
type Struct struct {
prop map[string]OtherStruct
}
func (s Struct) Prop() map[string]OtherStruct {
return s.prop
}
func (s Struct) Prop2() map[string]*OtherStruct {
prop := make(map[string]*OtherStruct, 0)
for k := range s.prop {
v := s.prop[k]
prop[k] = &v
}
return prop
}
func main() {
var s Struct;
// Simple getter
s = Struct{make(map[string]OtherStruct, 0)}
p1 := s.Prop()
fmt.Println(s) // &{map[]}
p1["something"] = OtherStruct{"test"}
fmt.Println(s) // {map[something:{test}]}
// Getter which copies map
s = Struct{make(map[string]OtherStruct, 0)}
p2 := s.Prop2()
fmt.Println(s) // &{map[]}
p2["something"] = &OtherStruct{"test"}
fmt.Println(s) // &{map[]}
}
Есть ли лучший способ инкапсулировать фрагменты / карты в Go? Или, может быть, я вообще не должен использовать инкапсуляцию в Go и использовать другой подход?