实施方式
make+copy
sClone = make([]T, len(s))
copy(sClone, s)
这是自Go工具链v1.15以来最快的方法。
- 缺点1:如果s为nil,则结果sClone为nil。
- 缺点2:有点冗长。
- 缺点3:T如果T在另一个包中声明了该包,则需要导入该类型的包含包。
make+append
sClone = append(make([] T,0,len(s)),s ...)
- 缺点1:如果s为nil,则结果sClone为nil。
- 缺点2:从Go工具链v1.16开始,这种方法总是比上述两行make+copy方法慢。切片越大,性能差异就越大。
- 缺点3:T如果T在另一个包中声明了该包,则需要导入该类型的包含包。
append
sClone = append([] T(nil),s ...)
//或
sClone = append([] T {},s ...)
- 缺点1:如果s是非零的空白切片,则结果sClone为零。
- 缺点2:可能会分配几个额外的元素插槽以适合内存块类的大小,这可能会影响性能。
- 缺点3:T如果T在另一个包中声明了该包,则需要导入该类型的包含包。
append B
sClone = append(s [:0:0 ],s ...)
- sClone如果结果为nil,则确保结果为nil;如果结果为nil,则确保结果s不s为nil。
- T即使T在另一个包中声明了该类型,也不需要导入其类型的包含包。
- 缺点1:可能会分配几个额外的元素插槽以适合内存块类的大小,这可能会影响性能。
- 缺点2:如果非零的长度s是从大切片中得出的,则长度为零,则sClone大切片都将引用基础元素序列。sClone即使仍使用基础元素序列,也永远不会收集垃圾,即使其容量sClone为零。
详细的实现
if s != nil {
sClone = make([]T, len(s))
copy(sClone, s)
} else {
sClone = nil
}
- 缺点1:它很冗长。
- 缺点2:T如果T在另一个包中声明了该包,则需要导入该类型的包含包。
泛型实现
泛型抢救?
import "slices"
sClone = slices.Clone(s)
缺点:需要导入软件包。
转自:https://github.com/go101/go101/wiki/There-is-not-a-perfect-slice-clone-way-in-Go