- Key features & common operations on Slices, Arrays, ...
- Dynamically-sized, in-memory sequence
- NOT Thread safe
- Pass-by-address-value
- All things pass by value
- maps, slices, channels, functions are passed by "address" value (like a pointer)
- If you pass a slice to a function/method, callee can mutate the slice
- How slices work
- Like an
ArrayList
in java
- Via literal
s0 := []string{"a", "b", "c"}
- Via
make
// capacity is 3
// contains 3 items with zero value (empty string)
s1 := make([]string, 3)
// capacity is 10
// contains 3 items with zero value (empty string)
s2 := make([]string, 3, 10)
- Auto resizes when out of capacity
// length == 1, capacity 3
s := make([]int32, 1, 2)
fmt.Println(s) // [0]
s = append(s, 1)
// When it grows the "reference" changes
s = append(s, 2)
s = append(s, 3)
cap(s) // capacity is 4, doubles when it grows
fmt.Println(s) // [0 1 2 3]
- Appending another slice
a := []int32{2, 3, 4}
b := []int32{5, 6}
a = append(a, b...)
fmt.Println(a) // [2 3 4 5 6]
- Other useful slice tricks
for index, value := range mySlice {
total += value
}
- Retrieve sub-slice
- Slicing is both common and efficient
- Get first
n
fmt.Println(s[:n]) // [0, 1, ...], first n-items, size=n
// Example:
s := []int{0, 1, 2, 3, 4, 5}
fmt.Println(s[:2]) // [0, 1], first 2 items, size=2
- Get last
n
fmt.Println(s[n:]) // size = len(s) - n
// Example:
s := []int{0, 1, 2, 3, 4, 5}
fmt.Println(s[2:]) // [2 3 4 5], size == 4 == len(s) - n
- Get middle
s := []int{0, 1, 2, 3, 4, 5}
fmt.Println(s[2:4]) // [2,3], closed-open range
- See Language spec
src := []string{"a", "b"}
// notice we are initializing all to zero value (not an empty slice)
dest := make([]string, len(src))
copy(dest, src)
colors := make([]string, 0)
fmt.Printf("Colors: %#v\n", colors)
type z string
before := []string{"a", "b", "c"}
after := make([]z, 0, len(before))
for _, v := range before {
after = append(after, z(v))
}
- (like a Sorted set)
s := []string{"c", "e", "a", "d", "b", "c", "b", "a"}
set := make(map[string]struct{}, len(s))
for _, v := range s {
set[v] = struct{}{}
}
uniq := make([]string, 0, len(set))
for k := range set {
uniq = append(uniq, k)
}
sort.Strings(uniq)
// uniq has [a b c d e]
- Fixed size
- Length is part of the type
- eg.
[3]string
and [4]string
are different types
- Rarely useful in practice (Use slice instead)
- Primary use case is as a building block for slices
- Sometimes used for multi-dimensional matrices
- go by example doc
- Pass-by-value
- Gotcha: Maps are not comparable with
==
- Compare index by index using
for
-range
- Really useful slice tricks
- https://www.practical-go-lessons.com/chap-21-slices
- https://www.practical-go-lessons.com/chap-15-pointer-type#slices
- https://go.dev/tour/moretypes/7
- https://gobyexample.com/slices
- https://codeburst.io/a-comprehensive-guide-to-slices-in-golang-bacebfe46669
- https://www.practical-go-lessons.com/chap-41-cheatsheet#slices