Working with array in Go.
Array in Go is just a data structure that hold a collection of elements of any type. Each element can be accessed by its index. Length of array is fixed at compile time and its size is a part of its type.
The type [n]T is an array of n values of type T. It can be declared as full declaration statement or in a short-hand format, with or without init values.
Array also can be declared in form of [...]T where its size will be determined by the compiler.
var holidays = [7]bool{}
seasons := [4]string{"Spring", "Summer", "Autumn", "Winter"}
weekDays := [7]int{1, 2, 3, 4, 5, 6, 7}
fruits := [...]string{"apple", "guava", "orange"} // type [3]string
visited := [10]bool{1: true, 3: true, 5: true, 7: true, 9: true}
sudoku := [9][9]int{}
Size of array is a part of its type and it is determined at the compile time
That means you cannot extend its size at run-time and cannot assign it to another type at run-time:
fruits := [...]string{"apple", "guava", "orange"} // type: [3]string
moreFruits := [4]string{"grapes"} // type: [4]string
moreFruits = fruits // compile error
Arrays are comparable if they have same type
firstArr := [3]int{1, 2, 3} // type: [3]int
secondArr := [3]int{1, 2, 3} // type: [3]int
thirdArr := [4]int{1, 2, 3, 4} // type: [4]int
fmt.Println(firstArr == secondArr) // true
fmt.Println(secondArr == thirdArr) // compile error
Each elements can be accessed by index or range over the array. Access index out of the array will cause a panic
var weekDays [7]string
weekDays[0] = "Sunday"
weekDays[1] = "Monday"
weekDays[2] = "Tuesday"
weekDays[3] = "Wednesday"
weekDays[4] = "Thursday"
weekDays[5] = "Friday"
weekDays[6] = "Saturday"
fmt.Println(weekDays[5])
fmt.Println("Days in a week:")
for _, day := range weekDays {
fmt.Printf("\t%s\n", day)
}
// fmt.Println(weekDays[7]) // panic: index out of bound
Passing an array to a method will create a copy of the original array
This means what you do with the copied array will not affect to the original array.
package main
import "fmt"
func main() {
fruits := [3]string{"apple", "orange"}
addGuava(fruits) // doesn't change values of variable "fruits"
}
func addGuava(fruits [3]string) {
fruits[2] = "guava"
}
Passing the pointer of the array to a function if you want to change its value in that function:
package main
import "fmt"
func main() {
fruits := [3]string{"apple", "orange"}
addGuava(&fruits) // change value of variable "fruits"
}
func addGuava(fruits *[3]string) {
fruits[2] = "guava"
}
Assign or range statement on an array will also create a copy of the original array
arr := [4]int{0, 1, 2, 3}
newArr := arr
fmt.Printf("%p != %p", &arr, &newArr) // 0xc000126000 != 0xc000126020
Interact with value of array while ranging over it will not affect the original value:
arr := [4]int{0, 1, 2, 3}
for _, v := range arr {
v += 100 // will not affect the original array values
}
fmt.Println(arr) // [0, 1, 2, 3]
If you want to change value of original array while ranging over it, use index instead:
arr := [4]int{0, 1, 2, 3}
for i := 0; i < len(arr); i++ {
arr[i] += 100
}
fmt.Println(arr) // [100 101 102 103]
Pointer of index and value inside range statement will be reused.
Notice that the pointers of i
and v
are the same in the result:
arr := [3]int{1, 2, 3}
for i, v := range arr {
fmt.Printf("i=%d, v=%d, &i=%p, &v: %p\n", i, v, &i, &v) // i, v point to the same addresses for each iteration
}
This will cause a problem if you use goroutine inside the for loop as below. Notice that only the last element is printed.
arr := [3]int{1, 2, 3}
for i, v := range arr {
go func() {
fmt.Printf("i=%d, v=%d, &i=%p, &v: %p\n", i, v, &i, &v)
}()
}
Define local variable to avoid the variables are captured is one way to avoid the above problem:
arr := [3]int{1, 2, 3}
for i, v := range arr {
i, v := i, v
go func() {
fmt.Printf("i=%d, v=%d, &i=%p, &v: %p\n", i, v, &i, &v)
}()
}
When do you use array?
Normally, array is used when the number of element is fixed at compile time. Example:
- Used in parsing network package where the length of the package is fixed. Example: TCP, UDP, DHCP, DNS packages, ...
- Used in hashing, encryption algorithms: MD5, Base64, Base58,...
- Represent a collection of fixed length elements like: days in a week, months in a year, ...