Slice Examples
This page was last reviewed on Mar 9, 2023.
Dot Net Perls
Slice. In Golang we use slices to represent parts of an underlying array. Slices, unlike arrays, can be changed easily—they are views into the underlying data.
Shows a sliceShows a sliceShows a slice
Slice notes. In Go slices have underlying arrays. A slice has no size as part of its type. And with built-in methods like cap() and append() we test and mutate slices.
sort Slice
Slice Remove Duplicates
Append. This example creates a slice of strings. It initially has 3 elements. We then use the append built-in to add 2 more strings to the slice.
Result The slice contains all 5 elements. A slice is an expandable, resizable array.
Shows a slice
package main import "fmt" func main() { elements := []string{"cat", "dog", "bird"} elements = append(elements, "fish", "snake") fmt.Println(elements) }
[cat dog bird fish snake]
Cap, capacity. A slice has an underlying array. This array has a capacity (a size). This is the number of elements that the slice can hold before being resized.
Detail The cap() built-in tells us the internal allocation heuristics of a slice. When it runs out of room, a slice's array doubles in size.
Here We create a slice of three elements. Its cap is 3. We then add a fourth element, and its capacity doubles to 6.
Shows a slice
package main import "fmt" func main() { elements := []int{100, 200, 300} // Capacity is now 3. fmt.Println(cap(elements)) // Append another element to the slice. elements = append(elements, 400) // Capacity is now 6. // ... It has doubled. fmt.Println(cap(elements)) }
3 6
Len, length. The len built-in returns the element count of a slice. An empty slice has a length of 0. This is not the same as capacity—only existing elements are counted.Shows a slice
package main import "fmt" func main() { // Create an empty slice. // ... Its length is 0. items := []string{} fmt.Println(len(items)) // Append a string and the slice now has a length of 1. items = append(items, "cat") fmt.Println(len(items)) }
0 1
Loop, range. With the range keyword we can loop over a slice. The value returned on each iteration is the index into the slice. We can access an element with it.
package main import "fmt" func main() { animals := []string{"bird", "dog", "fish"} // Loop over the slice. for v := range animals { fmt.Println(animals[v]) } }
bird dog fish
Loop, iteration. A three-part for-loop can be used to iterate over a slice. We start at 0 and continue while the index is less than the length of the slice (found with len).
package main import "fmt" func main() { colors := []string{"blue", "yellow", "orange"} // Loop over all indexes with a three-part for-loop. for v := 0; v < len(colors); v++ { fmt.Println(colors[v]) } }
blue yellow orange
Make. With this method we can create slices of a type and size. Internally slices must be initialized, and the make() method does this for us.
Note The first argument to make() is the type of the slice. The second argument is the length of elements. The third is the capacity.
Tip The capacity of a slice can be set as a performance optimization to avoid future allocations. A slice resizes automatically.
package main import "fmt" func main() { // Create a slice of 5 integers. values := make([]int, 5) // Assign some elements. values[0] = 100 values[4] = 200 // Loop over elements in slice and display them. for v := range values { fmt.Println(values[v]) } }
100 0 0 0 200
Copy. This built-in method receives two arguments: the destination slice and the source slice. The elements from the second arguments are copied into the first argument.
Tip Copy will copy as many elements as it can. If the destination slice is smaller than the source, all elements will be copied that fit.
package main import "fmt" func main() { slice1 := []int{10, 20, 30} slice2 := []int{0, 0, 0, 1000} // Display slice1 and slice2. fmt.Println(slice1) fmt.Println(slice2) // Copy elements from slice1 into slice2. copy(slice2, slice1) // Slice2 now has values from slice1. fmt.Println(slice2) }
[10 20 30] [0 0 0 1000] [10 20 30 1000]
Byte slice. This program creates a byte slice. It uses a string to initialize the slice. It then displays the byte count (with len) and converts the bytes back into a string.
package main import "fmt" func main() { values := []byte("birds") fmt.Println(values) // Display length of byte slice. fmt.Println(len(values)) // Create string copy of byte slice. copy := string(values) fmt.Println(copy) }
[98 105 114 100 115] 5 birds
Slices within slices. A slice is versatile. Once we have a slice, we can take further slices of it (subslices). We use the slice syntax on a slice of any element type.
Here We have an int slice. We take a subslice of the middle, end and start elements. This returns new partial slices.
package main import "fmt" func main() { value := []int{10, 20, 30, 40, 50} // Get slice of slice from index 2 to 4. // ... Last index is exclusive. partial := value[2:4] fmt.Println(partial) // Get slice from index 3 to end. partial = value[3:] fmt.Println(partial) // Get slice from start to index 3. partial = value[:3] fmt.Println(partial) }
[30 40] [40 50] [10 20 30]
Remove element. Slices do not have good support for element removal. Elements after the removed one must be shifted forward, which is slow.
Here We use two append calls to remove an element. The string "snake" is eliminated from the result slice.
Tip The map has a special operator (delete) for element removal. Due to a map's design, this is also much faster to perform.
package main import "fmt" func main() { // Example slice. animals := []string{"cat", "gopher", "snake", "bird", "dog"} // We want to remove element 2, which is snake. removeIndex := 2 // Create a new empty slice. result := []string{} // Append part before the removed element. // ... Three periods (ellipsis) are needed. result = append(result, animals[0:removeIndex]...) // Append part after the removed element. result = append(result, animals[removeIndex+1:]...) // Display results. fmt.Println(result) }
[cat gopher bird dog]
Index out of range. A slice has a size. And if we access an element out of the range of the size, we will get a runtime error. We must first check the len of a slice.
package main func main() { items := []int{10, 20, 30} // This will cause an error. items[100] = 10 }
panic: runtime error: index out of range
Initializer, variables. Often Go slice initializers use constants like 10 and 20. But we can also use variables (of the correct type).
Here The iteration variable "i" in the loop is used to create small two-element slices.
package main import "fmt" func main() { for i := 0; i < 3; i++ { items := []int{i, i + 1} fmt.Println(items) } }
[0 1] [1 2] [2 3]
Rune slices, strings. A string contains runes. We can get a slice of runes from a string with a conversion. We can modify the rune slice.
Detail We can convert the rune slice back into a string with a built-in method. A rune is a character in the string.
package main import "fmt" func main() { // Create a rune slice from a string. animal := "cat" slice := []rune(animal) // Modify the rune slice. slice[0] = 'm'; fmt.Println(slice) // Convert the rune slice back into a string. original := string(slice) fmt.Println(original) }
[109 97 116] mat
String slice map. Slices are separate from maps. But we can put slices (like string slices) in the values of a map and then append to those slices.
Map, String Slices
Convert slice to string. With strings.Join we can convert a slice into a string. For string slices, this is easy. But for int slices, we must have some special logic.
Convert Slice, String
A summary. The term "idiomatic" refers to languages. An idiomatic usage is one that sounds natural and is easy to understand. Idiomatic Go uses slices. We emphasize them over arrays.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Mar 9, 2023 (edit).
© 2007-2024 Sam Allen.