Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!
Comment¶
Array in Golang is similar to Array in Rust in the sense that the length of an array is part of its type and must be determined at compile time.
When an array is assigned to another variable or passed to a function as a parameter, it is copied! For this reason, array is not a good interface to use. Slice is prefer to array for function parameters.
import "reflect"Construct Arrays¶
Create an integer array of 0’s.
var arr[5]int
arr[0 0 0 0 0]reflect.TypeOf(arr)[5]intThe length of an array is part of its type which means that it must be known at compile time. Specifying a (non-const) variable as the length of an array will the code fail to compile.
n := 10
var vals[n]int
valsrepl.go:2:10: array length is not a constant: [n]intThe value of a const variable is known at compile time, so can you specify a const integer variable as the length of an array.
const n = 10
var arr[n]int
arr[0 0 0 0 0 0 0 0 0 0]Create a string array and explicitly specify the value at each index.
arr := [3]string{"how", "are", "you"}
arr[how are you]Define an int array with inferred length.
Note that ... must be used.
If omitted,
a slice instead of array is defined.
arr := [...]string{"how", "are", "you"}
arr[how are you]reflect.TypeOf(arr)[3]stringLength of an Array¶
arr := [...]string{"how", "are", "you"}
arr[how are you]len(arr)3Indexing an Array¶
arr := [...]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}
arr[0 10 20 30 40 50 60 70 80 90]arr[0]0arr[3]30arr[3:7][30 40 50 60]reflect.TypeOf(arr[3:7])[]intLoop Through an Array¶
The for ... range ... loop in Golang makes a copy of each value.
arr := [...]int{0, 1, 2}
arr[0 1 2]for i, v := range arr {
v *= 10
}
arr[0 1 2]for i, v := range arr {
arr[i] = v * 10
}
arr[0 10 20]Slice¶
A Slice in Golang is similar to a dynamic array (or vector) in other programming languages. However, due to Golang’s unique design (lacking of class), a Slice behaves different and sometimes confusing to users coming from other programming languages. A Slice in Golang is implemented as a descriptor (struct) containing a data pointer, a length and a capacity. Due to this design,
When you pass a Slice (value copy) to a function in Golang, the function can update existing values in the Slice (as the copied Slice in the function shares the same underlying data pointer as the original Slice).
The built-in function
appendcan be used to append values into a slice. Sinceappendtakes a Slice (instead of a pointer to a Slice) by value, it cannot update the original Slice descriptor (struct), so it has to return a new Slice descriptor. This sounds like append isn’t appending in place which is a misunderstanding.When there’s no capacity left in the underlying array, append has to allocate a new chunk of memory and copies value over. Appending isn’t in place in this case, but it’s true in any programming language.
When there’s capacity left in the udnerlying array, appending happens in place in the underlying array (as no new memory allocation is required). However, since a new slice descriptor is returned by
appendand the origial slice descriptor stays the same, the original slice descriptor is still a view of the old array window instead of the new updated array window.Sometimes, you want to pass a slice to another function for appending values and want the change to be reflected outside the function. To achieve this, you can pass a pointor to the Slice descriptor.
vec := []int{1, 2, 3}
vec[1 2 3]reflect.TypeOf(vec)[]intCreate an integer slice with length 5 and capacity 5 using the function make.
s1 := make([]int, 5)
s1[0 0 0 0 0]len(s1)5cap(s1)5Create an integer slice with length 5 and capacity 10 using the function make.
s2 := make([]int, 5, 10)
s2[0 0 0 0 0]len(s2)5cap(s2)10vec := []int{1, 2, 3}
vec[1 2 3]vec = append(vec, 10, 20, 30)
vec[1 2 3 10 20 30]v2 := []int{100, 200, 300, 400}
v2[100 200 300 400]vec = append(vec, v2...)
vec[1 2 3 10 20 30 100 200 300 400]Use Slice Instead of Array for Function Parameters¶
func updateSlice(s []int) {
s[4] = 750
}arr := [5]int{78, 89, 45, 56, 14}
arr[78 89 45 56 14]updateSlice(arr[:])
arr[78 89 45 56 750]vec := []int{78, 89, 45, 56, 14}
vecparsing go files in TempDir "/tmp/gonb_e532465a": /tmp/gonb_e532465a/main.go:3:1: expected declaration, found vecupdateSlice(vec)
vec[78 89 45 56 750]func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d %v\n",
s, len(x), cap(x), x)
}
%%
a := make([]int, 0, 5)
printSlice("a", a)
b := append(a, 1)
printSlice("b", b)
printSlice("a", a)
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&a))
data := *(*[5]int)(unsafe.Pointer(hdr.Data))
printSlice("a", data[:])a len=0 cap=5 []
b len=1 cap=5 [1]
a len=0 cap=5 []
a len=5 cap=5 [1 0 0 0 0]
func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d %v\n",
s, len(x), cap(x), x)
}
func myAppend(arr *[]int, val int) {
*arr = append(*arr, val)
}
%%
a := make([]int, 0, 5)
printSlice("a", a)
myAppend(&a, 1000)
printSlice("a", a)a len=0 cap=5 []
a len=1 cap=5 [1000]