在 go 中,从不同 goroutine 同时读写同一结构体的不同字段(如 `s.fielda` 和 `s.fieldb`)在语义上是线程安全的,因为它们本质上是独立的内存位置;但需警惕伪共享导致的性能下降,且绝对禁止在并发写期间变更结构体指针本身。
Go 的内存模型明确规定:对不同变量的并发读写是安全的,前提是这些变量不共享底层内存地址。结构体(struct)的每个字段在内存中通常占据独立的偏移位置(除非被编译器优化重排或存在填充),因此 apple.color 和 apple.size 是两个逻辑上分离的变量。如下代码在 Go 语言规范层面不会引发数据竞争(data race):
package main
import "time"
type Apple struct {
color string
size uint
}
func main() {
apple := &Apple{}
go func() {
apple.color = "red" // 写入字段 color
}()
go func() {
apple.size = 42 // 写入字段 size
}()
time.Sleep(10 * time.Millisecond) // 确保 goroutines 完成(仅用于演示)
}
运行 go run -race main.go 不会报告数据竞争——这验证了其语义安全性。
⚠️ 但需注意两个关键限制: