DO NOT use the return of append function to create new slice in Go
For Golang developers, it is very common to use append function to append new elements into slice. The common syntax is like below:
var slice := make([]int, 0)
slice = append(slice, 123)
And for some requirements, you may want to create a new slice based on an existing slice. We know the below the code will work perfectly. slice := []int{1,2,3}
newSlice := make([]int, 0)
newSlice = append(newSlice, append(slice, 4)...)
Below is complete example code to show the result:package main
import (
"fmt"
)
func main() {
// here create the origin slice with cap 10 to make sure that
// the slice is big enough to hold more data
slice := make([]int, 0, 10)
slice = append(slice, []int{1, 2, 3}...)
newSlice := make([]int, 0)
newSlice = append(newSlice, append(slice, 4)...)
fmt.Println(slice)
fmt.Println(newSlice)
fmt.Printf("The address of slice: %v\n", &slice[0])
fmt.Printf("The address of newSlice: %v\n", &newSlice[0])
}
The result is:[1 2 3]
[1 2 3 4]
The address of slice: 0xc000014050
The address of newSlice: 0xc00007a000
You can see the two slices have different addresses.However you may think if we can simplify the code by appending value to the origin slice and assign the return value to the newSlice variable like below:
slice := []int{1,2,3}
newSlice := make([]int, 0)
newSlice = append(slice, 4)
This looks simpler and cleaner, right? NO, this won't work! Let's see an example:
package main
import (
"fmt"
)
func main() {
// here create the origin slice with cap 10 to make sure that
// the slice is big enough to hold more data
slice := make([]int, 0, 10)
slice = append(slice, []int{1, 2, 3}...)
newSlice := make([]int, 0)
newSlice = append(slice, 4)
fmt.Println(slice)
fmt.Println(newSlice)
fmt.Printf("The address of slice: %v\n", &slice[0])
fmt.Printf("The address of newSlice: %v\n", &newSlice[0])
}
The result is:
[1 2 3]
[1 2 3 4]
The address of slice: 0xc00010a000
The address of newSlice: 0xc00010a000
See newSlice is pointing to the same address of slice?This is because append function does not guarantee that it always returns a new slice. It only reallocate a new slice when the capacity of the slice in the first parameter is not enough to hold more data. So if you are expecting to use append function to get a new slice like above, you will probably mess up the origin slice and get the wrong output.
So to be safe, if you want to get a new slice based on an existing slice, you use the code below:
slice := []int{1,2,3}
newSlice := make([]int, 0)
newSlice = append(newSlice, append(slice, 4)...)
Or below code if it is clearer.
slice := []int{1,2,3}
newSlice := make([]int, 0)
newSlice = append(newSlice, slice...)
newSlice = append(newSlice, 4)
I encountered this problem when I am practicing LeetCode problem 797.
Casino and Resort Spa Tunica-New Jersey
ReplyDeleteExperience the 보령 출장마사지 best gaming at the casino and resort 상주 출장마사지 in Tunica's 영주 출장마사지 New Jersey 서귀포 출장안마 area, a luxury resort with more than 2,000 slots, 24 table games, 고양 출장안마
Good article, but I think you can find useful information in Golang slices, an article I just wrote.
ReplyDelete