# Basics of `[N]T` (arrays) tutorial

• A fixed-length sequence of zero or more elements of a particular type.
• Arrays are copied when passing them as arguments.
``````var q [3]int = [3]int{1, 2, 3}
var r [3]int = [3]int{1, 2}

// if an “...” appears in place of the length, the length is determined by the initializers.
// The size must be a constant expression,
q := [...]int{1, 2, 3}

const (
USD Currency = iota
EUR
GBP
RMB
)

// Init with Index, value pairs.
// The pairs can appear in any order
symbol := [...]string{USD: "\$", EUR: "€", GBP: "£", RMB: "¥"}

// Some can be omitted (defines [0, 0, ..., -1])
r := [...]int{99: -1}``````

# Basics of `[]T` (slices) tutorial

• A slice type is written `[]T`
• A slice has three components: a `pointer`, a `length`, and a `capacity`.
• The `pointer` points to the first element of the array that is reachable through the slice
• The `length` is the number of slice elements
• The `capacity` is usually the number of elements between the start of the slice and the end of the underlying array.
• Copying a slice creates an alias for the underlying array.
• Unlike arrays, slices are not comparable.
• The only legal slice comparison is against `nil`.
• A `nil` slice behaves like any other zero-length slice
If you need to test whether a slice is empty, use `len(s) == 0`, not `s == nil`.
``````var s []int    // len(s) == 0, s == nil
s = nil        // len(s) == 0, s == nil
s = []int(nil) // len(s) == 0, s == nil
s = []int{}    // len(s) == 0, s != nil``````
``````package main

import "fmt"

func reverse(s []int) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}

func main() {
a := [...]int{0, 1, 2, 3, 4, 5}
reverse(a[:]) // modifies `a`
fmt.Println(a)
}``````
``````[5 4 3 2 1 0]
``````
The slice operator `s[i:j]`
• Creates a new slice that refers to elements `i` through `j-1` of the sequence `s`,
• When omitted, `i` is `0`, and `j` is `len(s)`.
• `0 ≤ i ≤ j ≤ cap(s)`
• Slicing beyond `cap(s)` causes a panic
• Slicing beyond `len(s)` extends the slice, so the result may be longer than the original

# How `append()` works discussion

``````func appendInt(x []int, y int) []int {
var z []int
zlen := len(x) + 1
if zlen <= cap(x) {
// There is room to grow.  Extend the slice.
z = x[:zlen]
} else {
// There is insufficient space.  Allocate a new array.
// Grow by doubling, for amortized linear complexity.
zcap := zlen
if zcap < 2*len(x) {
zcap = 2 * len(x)
}
z = make([]int, zlen, zcap)
copy(z, x)
}
z[len(x)] = y
return z
}``````

As we cannot know when `append()` grows the underlying array, we can’t assume that the original slice refers to the same array as the resulting slice, nor that it refers to a different one.

``````a := [...]int{0, 1, 2, 3}
b := a[1:2]
fmt.Println(b)
c := append(b, 99)
fmt.Println(c)
// a is affected by `append()` on `b`
fmt.Println(a)``````
``````[1]
[1 99]
[0 1 99 3]
``````

# Test the equality of two slices howto

``````func isEqual(a, b []int) bool {
if (a == nil) != (b == nil) {
return false
}

if len(a) != len(b) {
return false
}

for i := range a {
if a[i] != b[i] {
return false
}
}

return true
}``````

# Passing slices by value vs by pointer? discussion

It’s idiomatic to have functions like slice = doSomethingWithSlice(slice) and `less` so to see `doSomethingWithSlice(&slice)`

# Iterate in reverse order howto

``````s := []int{5, 4, 3, 2, 1}
for i := len(s)-1; i >= 0; i-- {
fmt.Printf(" %d", s[i])
}``````
``````1 2 3 4 5
``````

# Convert slice of strings to slice of int howto

• There is no concise way to do it:
``````import "strconv"

func sliceAtoi(sa []string) ([]int, error) {
si := make([]int, 0, len(sa))
for _, a := range sa {
i, err := strconv.Atoi(a)
if err != nil {
return si, err
}
si = append(si, i)
}
return si, nil
}``````

# Transform `[]int` to `string` with one line howto

``````a := []int{1, 2, 3}
s := strings.Trim(fmt.Sprint(a), "[]")
fmt.Println(s)``````
``````1 2 3
``````