Copy a slice in Go
In Go, a slice is a lightweight data structure that provides a flexible and convenient way to work with sequences of data. However, when working with slices, it's important to understand the difference between a shallow copy and a deep copy.
What is Shallow Copy?
A shallow copy creates a new slice with a new header pointing to the same underlying array as the original slice. This means that changes made to the elements of the new slice will be reflected in the original slice and vice versa.
What is Deep Copy?
A deep copy creates a new underlying array and copies the elements of the original slice into the new array. This ensures that the original and duplicate slices are completely independent of each other.
Let us look at different ways to copy or duplicate a slice in golang with examples.
Using the built-in copy()
function:
This method takes an original
slice of integers as an input and creates a new slice duplicate
of the same length. It then uses the built-in copy()
function to copy the elements of the original
slice into the duplicate
slice. The number of elements copied is the minimum length of the two slices.
package main
import (
"fmt"
)
func main() {
original := []int{1, 2, 3, 4, 5}
// Using the built-in `copy()` function
duplicate := CopySlice(original)
fmt.Println("Original Slice", original)
fmt.Println("Duplicate Slice", duplicate)
}
func CopySlice(original []int) []int {
duplicate := make([]int, len(original))
copy(duplicate, original)
return duplicate
}
Output
Original Slice [1 2 3 4 5]
Duplicate Slice [1 2 3 4 5]
Using the append()
function:
This method takes an original
slice of integers as an input, creates a new slice with nil
as its initial value, and then uses the append()
function to append all elements of the original
slice to the new slice.
By using the append() function and passing an existing slice as the last argument, it is possible to create a new slice with the same elements as the original slice.
package main
import (
"fmt"
)
func main() {
original := []int{1, 2, 3, 4, 5}
// Using the built-in `append()` function
duplicate := CopySlice(original)
fmt.Println("Original Slice", original)
fmt.Println("Duplicate Slice", duplicate)
}
func CopySlice(original []int) []int {
return append([]int(nil), original...)
}
Output
Original Slice [1 2 3 4 5]
Duplicate Slice [1 2 3 4 5]
Using a for
loop:
This method takes an original
slice of integers as an input, creates a new slice duplicate
of the same length, and then iterates over the elements of the original
slice using a for
loop. It then assigns the value of each element to the corresponding index of the duplicate
slice.
package main
import (
"fmt"
)
func main() {
original := []int{1, 2, 3, 4, 5}
// Using the `for`loop
duplicate := CopySlice(original)
fmt.Println("Original Slice", original)
fmt.Println("Duplicate Slice", duplicate)
}
func CopySlice(original []int) []int {
duplicate := make([]int, len(original))
for i, v := range original {
duplicate[i] = v
}
return duplicate
}
Output
Original Slice [1 2 3 4 5]
Duplicate Slice [1 2 3 4 5]
Using the make()
function with a composite literal:
This method takes an original
slice of integers as an input, creates a new slice duplicate
of the same length using the make()
function, and then uses the copy()
function to copy the elements of the original
slice into the duplicate
slice.
package main
import (
"fmt"
)
func main() {
original := []int{1, 2, 3, 4, 5}
// Using the `make()` function
duplicate := CopySlice(original)
fmt.Println("Original Slice", original)
fmt.Println("Duplicate Slice", duplicate)
}
func CopySlice(original []int) []int {
duplicate := make([]int, len(original))
copy(duplicate, original)
return duplicate
}
Output
Original Slice [1 2 3 4 5]
Duplicate Slice [1 2 3 4 5]
Using the reflect.Copy()
function:
This method takes an original
slice of integers as an input, creates a new slice duplicate of the same length using the make()
function, and then uses the reflect.Copy()
function to copy the elements of the original
slice into the duplicate
slice. The reflect.Copy()
function can copy elements from any data type that implements the SliceHeader
interface.
package main
import (
"fmt"
"reflect"
)
func main() {
original := []int{1, 2, 3, 4, 5}
// Using the `reflect.Copy()` function
duplicate := CopySlice(original)
fmt.Println("Original Slice", original)
fmt.Println("Duplicate Slice", duplicate)
}
func CopySlice(original []int) []int {
duplicate := make([]int, len(original))
reflect.Copy(reflect.ValueOf(duplicate), reflect.ValueOf(original))
return duplicate
}
Output
Original Slice [1 2 3 4 5]
Duplicate Slice [1 2 3 4 5]
Conclusion
In conclusion, creating a copy of a slice in Go is a simple task that can be achieved through a few different methods. The methods discussed in this article include:
- Using the built-in
copy()
function. - Using the
append()
function. - Using a
for
loop. - Using the
make()
function with a composite literal. - Using the
reflect.Copy()
function.
All of these methods will create a new slice with a new header pointing to the same underlying array as the original slice, which means that changes made to the elements of the new slice will be reflected in the original slice and vice versa.