在Go中,结构体按值复制(第一层深拷贝,嵌套结构体也按相同规则复制),而切片按值复制,但只复制结构体,而不是背后的数据数组:原始切片和复制的切片指向同一个底层数组,因此,通过一个切片的修改会反映在另一个切片上,除非通过copy()显式地复制数组。
切片复制的示例:
s1 := []int{1,2,3} s2 := s1 // 指向同一个缓冲区! s2[0] = 99 fmt.Println(s1) // [99 2 3] // 创建数组的副本: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 — 独立的
在复制结构体时:如果结构体包含指针字段、切片字段,则只复制引用,而不是值。
如何“克隆”切片,以使其更改不影响原始切片?
潜在的错误答案:只需执行 b := a。正确的:
copy,创建新切片并复制数据:newS := make([]int, len(a)) copy(newS, a)
故事
描述: 在动态生成数据库查询时,未复制结构体中的切片字段,导致数据在重复查询中交叉,给用户返回不正确的结果。
故事
描述: 在并行处理数据时,通过赋值创建了结构体的副本,并在一个goroutine中扩展切片,同时使用另一个原始切片。数据“覆盖”,导致不可预测的错误。
故事
描述: 使用缓冲结构,复制时通过赋值未考虑嵌套切片(浅拷贝),一个地方的更改影响了另一个缓冲区——结果很难追踪数据变化的来源。