Array Elements
Simple declaration:
Next expression declares a variable "numbers" as an array of ten (10) integers.
var numbers [10]int
Note: An array's length is part of its type, so arrays cannot be resized. This seems limiting, but don't worry; Go provides a convenient way of working with arrays.
Array initializers:
//file array_init.go
package main
import "fmt"
func main() {
// declare an array with two elements
var a [2]string
a[0] = "Hello" // first element
a[1] = "World" // second element
fmt.Println(a[0], a[1])
fmt.Println(a)
// declare array with initializers
primes := [6]int{2, 3, 5, 7, 11, 13}
fmt.Println(primes)
}
The range is used to create a form of the loop iteration over a slice or a map. When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.
//file range_scan.go
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
}
Output:
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
You can skip the index or value by assigning to "_" If you only want the index, drop the ", value" entirely.
//file range_values.go
package main
import "fmt"
func main() {
pow := make([]int, 10)
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
Output:
2
4
8
16
32
64
128
256
512
A slice is a dynamically-sized, flexible view into the elements of an array. In practice, slices are much more common than arrays.
The type []T is a slice with elements of type T.
In the next example we define an array "primes" then we create a slice "s" from element 1 (inclusive) to element 4 (inclusive).
//file array_slice.go
package main
import "fmt"
func main() {
primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4]
fmt.Println(s) // [3 5 7]
}
Note: Remember the element count start from 0 in Go.
A slice does not store any data, it just describes a section of an underlying array.
Changing the elements of a slice modifies the corresponding elements of its underlying array.
Other slices that share the same underlying array will see those changes.
//file array_references.go
package main
import "fmt"
func main() {
names := [4]string{
"John",
"Paul",
"George",
"Ringo",
}
fmt.Println(names)
b := names[1:3]
b[0] = "XXX"
fmt.Println(b)
fmt.Println(names)
}
When slicing, you may omit the high or low bounds to use their defaults instead.
The default is zero for the low bound and the length of the slice for the high bound.
For the array: var a [10]int
, next slice expressions are equivalent:
a[0:10]
a[:10]
a[0:]
a[:]
In the next example we use slice defaults to create 3 slices from the same array:
//fille default_boundery.go
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
s = s[1:4]
fmt.Println(s)
s = s[:2]
fmt.Println(s)
s = s[1:]
fmt.Println(s)
}
Output:
[3 5 7]
[3 5]
[5]
A slice has both a length and a capacity. The length of a slice is the number of elements it contains.
The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.
The length and capacity of a slice s can be obtained using the expressions len(s) and cap(s).
You can extend a slice's length by re-slicing it, provided it has sufficient capacity.
//file slice_cap.go
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Slice the slice to give it zero length.
s = s[:0]
printSlice(s)
// Extend its length.
s = s[:4]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
The zero value of a slice is nil. A nil slice has a length and capacity of 0 and has no underlying array.
//file nil_slice.go
package main
import "fmt"
func main() {
var s []int
fmt.Println(s, len(s), cap(s))
if s == nil {
fmt.Println("nil!")
}
}
Output:
[] 0 0
nil!
Slices can be created with the built-in make() function; this is how you create dynamically-sized arrays.
The make() function allocates a zeroed array and returns a slice that refers to that array:
a := make([]int, 5) // len(a)=5
To specify a capacity, pass a third argument to make
:
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4
//file slice_make.go
package main
import "fmt"
func main() {
a := make([]int, 5)
printSlice("a", a)
b := make([]int, 0, 5)
printSlice("b", b)
c := b[:2]
printSlice("c", c)
d := c[2:5]
printSlice("d", d)
}
func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d %v\n",
s, len(x), cap(x), x)
}
Output:
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0]
d len=3 cap=3 [0 0 0]
It is common to append new elements to a slice. Go provides a built-inappend function.
func append(s []T, vs ...T) []T
Examples:
//file slice_append.go
package main
import "fmt"
func main() {
var s []int
printSlice(s)
// append works on nil slices.
s = append(s, 0)
printSlice(s)
// The slice grows as needed.
s = append(s, 1)
printSlice(s)
// We can add more than one element at a time.
s = append(s, 2, 3, 4)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
Output:
len=0 cap=0 []
len=1 cap=2 [0]
len=2 cap=2 [0 1]
len=5 cap=8 [0 1 2 3 4]
Read next: Maps