实施方式

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 [:00 ],s ...)
  1. sClone如果结果为nil,则确保结果为nil;如果结果为nil,则确保结果s不s为nil。
  2. 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