How to perfectly clone a slice?
Go official wiki lists two ways to clone/copy a slice:
b = make([]T, len(a))
copy(b, a)
and
b = append([]T(nil), a...)
However, both of the two are not perfect.
- For the first way, the result slice
b
is not nil even if the source slicea
is nil. - For the second way, the result slice
b
is nil even if the source slicea
is a non-nil blank slice.
The following code will fix the problems of the above two ways.
b = nil
if a != nil {
b = make([]T, len(a))
copy(b, a)
}
The new way is quite verbose. Is there a one-line perfect solution? Yes, the following way is the best slice clone solution according to what I know.
b = append(a[:0:0], a...)
This solution guarantees that b
is nil if a
is nil and b
is not nil if a
is no nil.
It makes use of the fact that a slice derived from a nil slice is still a nil slice. And the three-index subslice form ensures that the result slice will not share any elements with the source slice.
(Note: The way introduced in this article is not the best solution universally. For some scenarios, the target slice is expected to be nil even if the source slice is a non-nil blank one, to avoid sharing underlying elements.)
(Note 2: There is an imperfection in the perfect clone implementation: the capacity of the result slice might be not the same as the length of the result slice, which leads to the following note 3.)
(Note 3: the append
way is a little inefficient in execution than the make+copy
way per pure-clone purpose.)
[update]: There is not a perfect way to clone slices in Go actually.
Please follow the official Twitter account of Go 101, @go100and1, to learn some Go details, facts, tips, etc, and read some Go articles from time to time.
Go 101 is a series of books about Go programming.
Books in Go 101 series
- Go (Fundamentals) 101 focuses on Go syntax/semantics (except custom generics related) and all kinds of runtime related things.
- Go Optimizations 101 provides some code performance optimization tricks, tips, and suggestions.
- Go Details & Tips 101 collects many details and provides several tips in Go programming.
- Go Generics 101 explains Go custom generics in detail.
Tapir started writing the Go 101 books and maintaining the go101.org website since 2016. New contents will continue being added to the books and the website from time to time. If you would like to, you can also support Go 101 by playing Tapir's games (for both Android and iPhone/iPad):
- Color Infection (★★★★★) - a physics based casual puzzle original game. 140+ levels.
- Rectangle Pushers (★★★★★) - a casual puzzle original game. 104+ levels.
- Let's Play With Particles - a casual action original game. Three game modes are included.