Golang slices

Basics

A slice is a dynamically sized, flexible view into the elements of an array. Apparently they are much more common than arrays. Initialization is pretty straight forward:

package main
 
import "fmt"
 
func main() {
	primes := [6]int{2, 3, 5, 7, 11, 13}
 
	var s []int = primes[1:4]
	fmt.Println(s)
}

Slices are like references. Change something in the slice and the [Golang Arrays](Golang Arrays) it references also changes

package main
 
import "fmt"
 
func main() {
	names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names)
 
	a := names[0:2]
	b := names[1:3]
	fmt.Println(a, b)
 
	b[0] = "XXX"
	fmt.Println(a, b)
	fmt.Println(names)
}

Slices can contain any type, including other slices:

package main
 
import (
	"fmt"
	"strings"
)
 
func main() {
	// Create a tic-tac-toe board.
	board := [][]string{
		[]string{"_", "_", "_"},
		[]string{"_", "_", "_"},
		[]string{"_", "_", "_"},
	}
 
	// The players take turns.
	board[0][0] = "X"
	board[2][2] = "O"
	board[1][2] = "X"
	board[1][0] = "O"
	board[0][2] = "X"
 
	for i := 0; i < len(board); i++ {
		fmt.Printf("%s\n", strings.Join(board[i], " "))
	}
}
 

Slice literals

A slice literal is like an array, but without the length, so we add more stuff to it later

package main
 
import "fmt"
 
func main() {
	q := []int{2, 3, 5, 7, 11, 13}
	fmt.Println(q)
 
	r := []bool{true, false, true, true, false, true}
	fmt.Println(r)
 
	s := []struct {
		i int
		b bool
	}{
		{2, true},
		{3, false},
		{5, true},
		{7, true},
		{11, false},
		{13, true},
	}
	fmt.Println(s)
}

Slice defaults

You can omit high and low bounds. As one would expect these default to 0 and slice length respectively

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)
}

Slice length and capacity

One can lookup slice length (length of the slice) and capacity (length of the array the slice references)

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)
}

Nil slices

Empty slices are equal to nil. Maybe that’s a good idea, maybe it isn’t. Typing this i’m too tired to give rational input to this philosophical quagmire.

package main
 
import "fmt"
 
func main() {
	var s []int
	fmt.Println(s, len(s), cap(s))
	if s == nil {
		fmt.Println("nil!")
	}
}

Make

Slices can be created with the make function, this way you can treat them like arrays that we know and love.

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)
}

Append

New elements can be added to a slice with the [[https://golang.org/pkg/builtin/#append]\[append]] function

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)
}

Range

You can iterate over slices with range

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)
	}
}

Index or value can be skipped by using _. In case you only want the index, just omit the second variable entirely:

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)
	}
}

1
2
4
8
16
32
64
128
256
512