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
reflect.TypeOf(arr)
The 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
vals
The 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
Create a string array and explicitly specify the value at each index.
arr := [3]string{"how", "are", "you"}
arr
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
reflect.TypeOf(arr)
Length of an Array¶
arr := [...]string{"how", "are", "you"}
arr
len(arr)
Indexing an Array¶
arr := [...]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}
arr
arr[0]
arr[3]
arr[3:7]
reflect.TypeOf(arr[3:7])
Loop Through an Array¶
The for ... range ... loop in Golang makes a copy of each value.
arr := [...]int{0, 1, 2}
arr
for i, v := range arr {
v *= 10
}
arr
for i, v := range arr {
arr[i] = v * 10
}
arr
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
reflect.TypeOf(vec)
Create an integer slice with length 5 and capacity 5 using the function make.
s1 := make([]int, 5)
s1
len(s1)
cap(s1)
Create an integer slice with length 5 and capacity 10 using the function make.
s2 := make([]int, 5, 10)
s2
len(s2)
cap(s2)
vec := []int{1, 2, 3}
vec
vec = append(vec, 10, 20, 30)
vec
v2 := []int{100, 200, 300, 400}
v2
vec = append(vec, v2...)
vec
Use Slice Instead of Array for Function Parameters¶
func updateSlice(s []int) {
s[4] = 750
}
arr := [5]int{78, 89, 45, 56, 14}
arr
updateSlice(arr[:])
arr
vec := []int{78, 89, 45, 56, 14}
vec
updateSlice(vec)
vec
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[:])
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)