Array
In Go, an array is a numbered sequence of elements of a specific length.
The Slice is more common in Go code,
but arrays are useful in some special scenarios.
package main
import "fmt"
func main() {
var arr [5]int
fmt.Println("Empty: ", arr)
// Create an array hold exactly 5 integers.
// The length and the type of elements are both part of the array's type.
// The default value of an array is the zero value of its element type, in this case 0.
arr[4] = 1 // Assignment.
fmt.Println("Set: ", arr)
fmt.Println("Get: ", arr[4])
fmt.Println("Len: ", len(arr)) // The built-in function.
b := [5]int{1, 2, 3, 4, 5} // Declare and initialize in one line.
fmt.Println("Declare and initialize: ", b)
c := [...]int{1, 2, 3, 4, 5} // The compiler counts the number of elements.
fmt.Println("Declare and initialize with ellipsis: ", c)
d := [...]int{1, 2, 5: 5} // Set the 5th element to 5, the between are 0.
fmt.Println("Declare and initialize with explicit index: ", d)
var e [2][3]int // We can also create multi-dimensional arrays.
for i := range 2 {
for j := range 3 {
e[i][j] = i + j
}
}
fmt.Println("2-dimensional array: ", e)
f := [2][3]int{
{1, 2, 3},
{4, 5, 6},
} // We can also declare and initialize multi-dimensional arrays in one line.
fmt.Println("2-dimensional array: ", f)
}
/*
Empty: [0 0 0 0 0]
Set: [0 0 0 0 1]
Get: 1
Len: 5
Declare and initialize: [1 2 3 4 5]
Declare and initialize with ellipsis: [1 2 3 4 5]
Declare and initialize with explicit index: [1 2 0 0 0 5]
2-dimensional array: [[0 1 2] [1 2 3]]
2-dimensional array: [[1 2 3] [4 5 6]]
*/Slice
Slice is important in Go, giving more powerful interface to sequence than Array.
package main
import (
"fmt"
"slices"
)
func main() {
var str []string
fmt.Println("Uninitialized slice:", str, str == nil, len(str) == 0)
// The slice is typed only be its elements type without the length.
// An uninitialized slice is nil and has a length of 0.
str = make([]string, 3)
fmt.Println("Initialized slice:", str, len(str) == 3, cap(str) == 3)
// To create a nonzero length slice, we can use the built-in `make`
// By default, the length is equal to its capacity, but we can specify a different capacity as well.
// e.g. `str = make([]string, 3, 5)`, capacity is 5 but length is 3, we can append up to 5 without allocating a new array.
str[0] = "Hello,"
str[1] = "world!"
fmt.Println("After assigning values:", str)
// Use like an array, but we can only assign values up to its length, not capacity.
/* More than array */
str = append(str, "Go")
str = append(str, "is", "interesting")
str[2] = "Not overwriting"
fmt.Println("After appending values:", str, len(str), cap(str))
// We can append values to a slice, and it will automatically resize if needed.
// The elements appended will be added behind the length, not behind the last element.
ing := make([]string, len(str))
copy(ing, str)
fmt.Println("Copied slice:", ing, len(ing) == len(str))
// We can use copy to copy a slice.
// But unlike append, copy will not resize, it will cut off at the length of dst.
slice1 := str[1:4]
slice2 := str[3:]
slice3 := str[:5]
fmt.Println("Sliced slices:", slice1, slice2, slice3)
// Just like in Python, we have a "slice" operator to slice a slice.
chars := []string{"G", "o", "l", "a", "n", "g"}
// We can declare and initialize a slice by a slice literal in one line.
chars2 := []string{"G", "o", "l", "a", "n", "g"}
if slices.Equal(chars, chars2) {
fmt.Println("Equal slices:", chars, chars2)
}
// The "slices" package provides some utilities for slice.
twoD := make([][]int, 3)
for i := range 3 {
innerLen := i + 1
twoD[i] = make([]int, innerLen)
for j := range innerLen {
twoD[i][j] = i + j
}
}
fmt.Println("Two-dimensional slice:", twoD)
// Like array, we can create multi-dimensional slices
// But unlike array, the length of each inner dimension can be varied.
}
/*
Uninitialized slice: [] true true
Initialized slice: [ ] true true
After assigning values: [Hello, world! ]
After appending values: [Hello, world! Not overwriting Go is interesting] 6 6
Copied slice: [Hello, world! Not overwriting Go is interesting] true
Sliced slices: [world! Not overwriting Go] [Go is interesting] [Hello, world! Not overwriting Go is]
Equal slices: [G o l a n g] [G o l a n g]
Two-dimensional slice: [[0] [1 2] [2 3 4]]
*/Especially, when we append a nil slice, it will be allocated space and append automatically and return the allocated slice.
var nilSlice []string
nilSlice = append(nilSlice, "Hello")
fmt.Println("Append to nil slice:", nilSlice, len(nilSlice) == 1)
/*
Append to nil slice: [Hello] true
*/Map
Map in Go is a associative structure like Hash in Java and Dict in Python
package main
import (
"fmt"
"maps"
)
func main() {
m := make(map[string]int)
// Create a map by built-in `make(map[key-type]value-type)` function.
m["k1"] = 10
m["k2"] = 20
val1 := m["k1"]
val2 := m["k3"]
fmt.Println("map:", m)
fmt.Println("val1:", val1)
fmt.Println("val2:", val2)
// Set pairs and get value of a key by assignments.
// Especially, if the key does not exist, the zero value of the value type is returned.
fmt.Println("len:", len(m))
// The built-in `len()` function returns the number of key-value pairs when its argument is a map.
delete(m, "k2")
fmt.Println("map:", m)
// The built-in `delete()` function deletes the key-value pair from the map.
clear(m)
fmt.Println("map after clear:", m)
// The built-in `clear()` removes all key-value pairs from the map.
_, prs := m["k2"]
fmt.Println("prs:", prs)
// In fact, when we get a value of a key, it will return two values.
// The second one is a boolean indicating whether the key exists in the map or not.
// It is useful to distinguish between that map is storing a zero value(like 0, "") or missing key.
m2 := map[string]int{"foo": 1, "bar": 2}
m3 := map[string]int{"foo": 1, "bar": 2}
if maps.Equal(m2, m3) {
fmt.Println("m2 and m3 are equal")
}
// We can also create a map and initialize a map by a map literal in one line.
}
/*
map: map[k1:10 k2:20]
val1: 10
val2: 0
len: 2
map: map[k1:10]
map after clear: map[]
prs: false
m2 and m3 are equal*/