Arrays

In Go, an array is a numbered sequence of elements of a specific length.

  1. package main
  2. import "fmt"
  3. func main() {
  4. // Here we create an array a that will hold exactly 5 ints. The type of elements and length are both part of the array’s type.
  5. // By default an array is zero-valued, which for ints means 0s.
  6. var a [5]int
  7. fmt.Println("emp:", a)
  8. // We can set a value at an index using the array[index] = value syntax,
  9. // and get a value with array[index].
  10. a[4] = 100
  11. fmt.Println("set:", a)
  12. fmt.Println("get:", a[4])
  13. // The builtin len returns the length of an array.
  14. fmt.Println("len:", len(a))
  15. // Use this syntax to declare and initialize an array in one line.
  16. b := [5]int{1, 2, 3, 4, 5}
  17. fmt.Println("dcl:", b)
  18. // Array types are one-dimensional,
  19. // but you can compose types to build multi-dimensional data structures.
  20. var twoD [2][3]int
  21. for i := 0; i < 2; i++ {
  22. for j := 0; j < 3; j++ {
  23. twoD[i][j] = i + j
  24. }
  25. }
  26. fmt.Println("2d: ", twoD)
  27. }
emp [0 0 0 0 0]
set: [0 0 0 0 100]
get: 100              
len: 5                
dcl: [1 2 3 4 5]      
2d:  [[0 1 2] [1 2 3]]

Slices

Slices are a key data type in Go, giving a more powerful interface to sequences than arrays.

package main

import "fmt"

func main() {
    s := make([]string, 3)
    fmt.Println("emp: ", s)

    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    fmt.Println("set: ", s)
    fmt.Println("get: ", s[2])

    fmt.Println("len: ", len(s))

    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println("apd: ", s)

    c := make([]string, len(s))
    copy(c, s)
    fmt.Println("cpy: ", c)

    l := s[2:5]
    fmt.Println("sl1: ", l)

    l = s[:5]
    fmt.Println("sl2: ", l)

    l = s[2:]
    fmt.Println("sl3: ", l)

    t := []string{"g", "h", "i"}
    fmt.Println("dcl: ", t)
    fmt.Printf("type: %T\n", t)

    var t1 = [3]string{"g", "h", "i"}
    fmt.Println("dcl: ", t1)
    fmt.Printf("type: %T\n", t1)

    twoD := make([][]int, 3)
    for i := 0; i < 3; i++ {
        innerlen := i + 1
        twoD[i] = make([]int, innerlen)
        for j := 0; j < innerlen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}
emp:  [  ]
set:  [a b c]           
get:  c                 
len:  3                 
apd:  [a b c d e f]     
cpy:  [a b c d e f]     
sl1:  [c d e]           
sl2:  [a b c d e]       
sl3:  [c d e f]         
dcl:  [g h i]           
type: []string          
dcl:  [g h i]           
type: [3]string         
2d:  [[0] [1 2] [2 3 4]]

Maps

Maps are Go’s built-in associative data type (sometimes called hashes or dicts in other languages).

package main

import "fmt"

func main() {
    // To create an empty map, use the builtin make: make(map[key-type]val-type).
    m := make(map[string]int)

    // Set key/value pairs using typical name[key] = val syntax.
    m["k1"] = 7
    m["k2"] = 13

    // Printing a map with e.g. fmt.Println will show all of its key/value pairs.
    fmt.Println("map:", m)

    // Get a value for a key with name[key].
    v1 := m["k1"]
    fmt.Println("v1: ", v1)

    // The builtin len returns the number of key/value pairs when called on a map.
    fmt.Println("len:", len(m))

    // The builtin delete removes key/value pairs from a map.
    delete(m, "k2")
    fmt.Println("map:", m)

    // The optional second return value when getting a value from a map indicates 
    // if the key was present in the map. This can be used to disambiguate between 
    // missing keys and keys with zero values like 0 or "". Here we didn’t need 
    // the value itself, so we ignored it with the blank identifier _.
    _, prs := m["k2"]
    fmt.Println("prs:", prs)

    // You can also declare and initialize a new map in the same line with this syntax.
    n := map[string]int{"foo": 1, "bar": 2}
    fmt.Println("map:", n)
}
map: map[k1:7 k2:13]
v1: 7                
len: 2               
map: map[k1:7]       
prs false            
map: map[bar:2 foo:1]

Range

range iterates over elements in a variety of data structures. Let’s see how to use range with some of the data structures we’ve already learned.

package main

import "fmt"

func main() {
    // Here we use range to sum the numbers in a slice. Arrays work like this too.
    nums := []int{2, 3, 4}
    sum := 0
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:", sum)

    // range on arrays and slices provides both the index and value for each entry. 
    // Above we didn’t need the index, so we ignored it with the blank identifier _. 
    // Sometimes we actually want the indexes though.
    for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
    }

    // range on map iterates over key/value pairs.
    kvs := map[string]string{"a": "apple", "b": "banana"}
    for k, v := range kvs {
        fmt.Printf("%s -> %s\n", k, v)
    }

    // range can also iterate over just the keys of a map.
    for k := range kvs {
        fmt.Println("key:", k)
    }

    // range on strings iterates over Unicode code points. 
    // The first value is the starting byte index of the rune 
    // and the second the rune itself. See Strings and Runes for more details.
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}
sum: 9
index: 1   
a -> apple 
b -> banana
key: a     
key: b     
0 103      
1 111