💻 Tech
In the previous journal, we see the side effects of creating and appending an item to a slice of a slice. We saw how we can utilize the copy command and how maximizing the capacity can lead to the creation of a new backing array.
Let’s revisit the append side effect. When you append an item to a slice of a slice when the length and capacity of the new slice are not equal, you’ll modify the backing array. This is why the address 0xc000074090 was modified from kamusta to MUDOU. As we learned from the previous journal, just increasing the slice to be copied to just one, will cause the length and capacity to be both 3. But we don’t need to do that. We can use what we call a 3-index-slice.
Demo program 1:
func main() {
fmt.Println("#####")
fmt.Println("original slice")
greetings := []string{"ola", "nihao", "salut", "oi", "kamusta"}
displaySlice(greetings)
fmt.Println("\n#####")
fmt.Println("slice of slice")
greetings1 := greetings[2:4]
displaySlice(greetings1)
fmt.Println("\n#####")
fmt.Println("side effect: modified new slice index")
greetings1 = append(greetings1, "MUDOU")
fmt.Println("original slice")
displaySlice(greetings)
fmt.Println("slice of slice")
displaySlice(greetings1)
}
func displaySlice(s []string) {
fmt.Printf("len:%v, cap:%v\n", len(s), cap(s))
for i, v := range s {
fmt.Printf("%v %v %v\n", i, &s[i], v)
}
}
Demo program 1 output:
#####
original slice
len:5, cap:5
0 0xc000074050 ola
1 0xc000074060 nihao
2 0xc000074070 salut
3 0xc000074080 oi
4 0xc000074090 kamusta
#####
slice of slice
len:2, cap:3
0 0xc000074070 salut
1 0xc000074080 oi
#####
side effect: modified new slice index
original slice
len:5, cap:5
0 0xc000074050 ola
1 0xc000074060 nihao
2 0xc000074070 salut
3 0xc000074080 oi
4 0xc000074090 MUDOU
slice of slice
len:3, cap:3
0 0xc000074070 salut
1 0xc000074080 oi
2 0xc000074090 MUDOU
You’ll notice greetings[2:4:4]. The 3rd index is the capacity. We’re saying that we want to reference the 2nd up to 3rd index of the greetings slice and set up to the a capacity of 4. You might notice that the output shows len:2, cap:2, so where’s the value of here? So let’s starts from the original slice. Original slice has 5 items. The new slice starts at the 2nd index. Let’s say we want to the capacity to be 2 only (since the new slice is with length=2). Doing so we can max out the capacity. From the 2nd index, we want the capacity to be until 3rd index, then we add one, resulting to 4. Why add one? That’s just the convention. Even [2:4] actually ends at 3, we just add one because it’s like saying 2nd index up to the index before the 4th index. So with [2:4:4], we’re saying the capacity starting from the 2nd index up to the index before the 4th index. Phew, that’s a mouthful.
You will see in the output that the resulting new slice has items with new addresses. This is again because when we append to an already maxed slice, it results to creating a new a backing array.
Demo program 2:
func main() {
fmt.Println("#####")
fmt.Println("original slice")
greetings := []string{"ola", "nihao", "salut", "oi", "kamusta"}
displaySlice(greetings)
fmt.Println("\n#####")
fmt.Println("slice of slice")
greetings1 := greetings[2:4:4] // from [2:4] to [2:4:4]
displaySlice(greetings1)
fmt.Println("\n#####")
fmt.Println("new slice is not affected")
greetings1 = append(greetings1, "MUDOU")
fmt.Println("original slice")
displaySlice(greetings)
fmt.Println("slice of slice")
displaySlice(greetings1)
}
func displaySlice(s []string) {
fmt.Printf("len:%v, cap:%v\n", len(s), cap(s))
for i, v := range s {
fmt.Printf("%v %v %v\n", i, &s[i], v)
}
}
Demo program 2 output:
#####
original slice
len:5, cap:5
0 0xc0000ae000 ola
1 0xc0000ae010 nihao
2 0xc0000ae020 salut
3 0xc0000ae030 oi
4 0xc0000ae040 kamusta
#####
slice of slice
len:2, cap:2
0 0xc0000ae020 salut
1 0xc0000ae030 oi
#####
new slice is not affected
original slice
len:5, cap:5
0 0xc0000ae000 ola
1 0xc0000ae010 nihao
2 0xc0000ae020 salut
3 0xc0000ae030 oi
4 0xc0000ae040 kamusta
slice of slice
len:3, cap:4
0 0xc0000a8040 salut
1 0xc0000a8050 oi
2 0xc0000a8060 MUDOU