Golang 中的不可变结构
Immutable Struct in Golang
是否可以在 Golang 中定义不可变结构?一旦初始化,则只对结构的字段进行读取操作,不修改字段值。如果是这样,怎么做。
通过使其成员不导出并提供读取器,可以使结构在其包外只读。例如:
package mypackage
type myReadOnly struct {
value int
}
func (s myReadOnly) Value() int {
return s.value
}
func NewMyReadonly(value int) myReadOnly{
return myReadOnly{value: value}
}
和用法:
myReadonly := mypackage.NewMyReadonly(3)
fmt.Println(myReadonly.Value()) // Prints 3
无法以一般方式将 fields/variables 标记为只读。您唯一可以做的就是将 fields/variable 标记为未导出(第一个字母小)并提供 public 吸气剂以防止其他包编辑变量。
在 Go 中无法定义不可变结构:结构字段是可变的,const 关键字不适用于它们。然而,Go 使得通过简单的赋值复制整个结构变得容易,因此我们可能认为通过值传递参数是具有不可变性所需的全部,但代价是复制。
但是,不出所料,这不会复制指针引用的值。由于内置集合(映射、切片和数组)是引用并且是可变的,复制包含其中之一的结构只是将指针复制到相同的底层内存。
示例:
type S struct {
A string
B []string
}
func main() {
x := S{"x-A", []string{"x-B"}}
y := x // copy the struct
y.A = "y-A"
y.B[0] = "y-B"
fmt.Println(x, y)
// Outputs "{x-A [y-B]} {y-A [y-B]}" -- x was modified!
}
注意 : 所以你必须非常小心,如果你按值传递参数,不要假设不变性。
有一些 deepcopy 库尝试使用(慢速)反射来解决这个问题,但由于无法通过反射访问私有字段,因此它们不够用。因此,避免竞争条件的防御性复制将很困难,需要大量样板代码。 Go 甚至没有可以对此进行标准化的 Clone 接口。
是否可以在 Golang 中定义不可变结构?一旦初始化,则只对结构的字段进行读取操作,不修改字段值。如果是这样,怎么做。
通过使其成员不导出并提供读取器,可以使结构在其包外只读。例如:
package mypackage
type myReadOnly struct {
value int
}
func (s myReadOnly) Value() int {
return s.value
}
func NewMyReadonly(value int) myReadOnly{
return myReadOnly{value: value}
}
和用法:
myReadonly := mypackage.NewMyReadonly(3)
fmt.Println(myReadonly.Value()) // Prints 3
无法以一般方式将 fields/variables 标记为只读。您唯一可以做的就是将 fields/variable 标记为未导出(第一个字母小)并提供 public 吸气剂以防止其他包编辑变量。
在 Go 中无法定义不可变结构:结构字段是可变的,const 关键字不适用于它们。然而,Go 使得通过简单的赋值复制整个结构变得容易,因此我们可能认为通过值传递参数是具有不可变性所需的全部,但代价是复制。
但是,不出所料,这不会复制指针引用的值。由于内置集合(映射、切片和数组)是引用并且是可变的,复制包含其中之一的结构只是将指针复制到相同的底层内存。
示例:
type S struct {
A string
B []string
}
func main() {
x := S{"x-A", []string{"x-B"}}
y := x // copy the struct
y.A = "y-A"
y.B[0] = "y-B"
fmt.Println(x, y)
// Outputs "{x-A [y-B]} {y-A [y-B]}" -- x was modified!
}
注意 : 所以你必须非常小心,如果你按值传递参数,不要假设不变性。
有一些 deepcopy 库尝试使用(慢速)反射来解决这个问题,但由于无法通过反射访问私有字段,因此它们不够用。因此,避免竞争条件的防御性复制将很困难,需要大量样板代码。 Go 甚至没有可以对此进行标准化的 Clone 接口。