Created
December 26, 2021 18:52
-
-
Save Tochemey/d49ef8b37a59018d2ee44dd5e454996c to your computer and use it in GitHub Desktop.
golang slice internal behaviour
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
func main() { | |
// This demonstrates the internal of go slice and what happens when slice reaches its capacity and why to be careful when appending to slice | |
// define an array of 5 elements | |
arr := [...]int{1, 2, 3, 4, 5} | |
fmt.Println(arr) // [1 2 3 4 5] | |
// let us create a slice from that array | |
sl := arr[2:4] | |
fmt.Println(sl) // [3 4] | |
// let us set the element at index 0 to zero on the slice | |
sl[0] = 0 | |
fmt.Println(sl) // [0 4] | |
fmt.Printf("len: %v, cap: %v, %v\n", len(sl), cap(sl), sl) // len: 2 cap: 3 [0 4] | |
// let us print the previous array from which the slice has been created. | |
// You will notice that the element at index 2 in the array has changed from 3 to 0 even though | |
// we only change the slice element at index 0. | |
// The lesson here is that you can create a slice from an original array and modification to that slice can | |
// easily affect that array. The reason is that the Go runtime creates a struct which points to the array with additional fields: len and cap | |
// reference https://golang.org/src/runtime/slice.go | |
fmt.Println(arr) // [1 2 0 4 5] | |
// let us append to the slice and print the slice and the underlying array | |
sl = append(sl, 9) | |
fmt.Println(sl) // [0 4 9] | |
fmt.Printf("len: %v, cap: %v, %v\n", len(sl), cap(sl), sl) // len: 3 cap: 3 [0 4 9] | |
// let us print the underlying array memory address | |
fmt.Printf("%p\n", &sl[0]) | |
// Here you will notice that the last element in the underlying array changes from 5 to 9. The reason here is until reaching a starting capacity, appending a slice will change items in original array | |
fmt.Println(arr) // [1 2 0 4 9] | |
// let us add another element to the slice | |
sl = append(sl, 9) | |
fmt.Println(sl) // [0 4 9 9] | |
// Here you will see when reaching capacity, slice is copying its "array slice" into new fragment of memory to fulfill this behaviour. It's capacity is doubled an we can start appending again. | |
// while the original array is left unchanged | |
fmt.Printf("len: %v, cap: %v, %v\n", len(sl), cap(sl), sl) // // len: 4 cap: 6 [0 4 9 9] | |
fmt.Printf("%p\n", &sl[0]) | |
// after the element to the slice you can observe that is not added to the underlying array but to the slice. The reason is that array are fixed-size lists that cannot be resized | |
fmt.Println(arr) // [1 2 0 4 9] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment