如何通过Go语言实现并发安全的不变对象模式设计?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1043个文字,预计阅读时间需要5分钟。
Go 语言本身不提供 `final`、`const struct` 或只读字段语法,也不支持不可变的概念。所谓的不可变通常是指变量的值在初始化后不能被修改。在 Go 中,可以通过以下方式实现类似不可变的效果:
- 永远不要在结构体方法中返回
[][]byte、[]string、map[string]int等可变容器的原始引用;该复制就复制 - 构造函数(如
NewConfig())应做深拷贝或只接受只读输入(如io.Reader、string) - 如果结构体含指针字段(比如
*bytes.Buffer),即使字段未导出,也需在访问器中返回副本(buf.Bytes()而非buf)
并发安全 ≠ 不可变,但不可变是最省心的并发安全手段
很多人以为加个 sync.RWMutex 就算“线程安全”,其实只是掩盖了数据可变带来的复杂性。而真正不可变的对象(比如每次更新都返回新实例),天然无锁、无竞态,go run -race 也扫不出问题。
本文共计1043个文字,预计阅读时间需要5分钟。
Go 语言本身不提供 `final`、`const struct` 或只读字段语法,也不支持不可变的概念。所谓的不可变通常是指变量的值在初始化后不能被修改。在 Go 中,可以通过以下方式实现类似不可变的效果:
- 永远不要在结构体方法中返回
[][]byte、[]string、map[string]int等可变容器的原始引用;该复制就复制 - 构造函数(如
NewConfig())应做深拷贝或只接受只读输入(如io.Reader、string) - 如果结构体含指针字段(比如
*bytes.Buffer),即使字段未导出,也需在访问器中返回副本(buf.Bytes()而非buf)
并发安全 ≠ 不可变,但不可变是最省心的并发安全手段
很多人以为加个 sync.RWMutex 就算“线程安全”,其实只是掩盖了数据可变带来的复杂性。而真正不可变的对象(比如每次更新都返回新实例),天然无锁、无竞态,go run -race 也扫不出问题。

