Slices are one of Go's most versatile and frequently used data structures. They provide a convenient view into an underlying array and are used extensively throughout Go programs.
A slice is a reference to a contiguous segment of an array. Unlike arrays, slices are dynamic in size.
// Create a slice with a literal
numbers := []int{1, 2, 3, 4, 5}
// Create an empty slice with make
slice := make([]int, 5) // slice of length 5, capacity 5
slice := make([]int, 0, 10) // slice of length 0, capacity 10
// Create a slice from an existing array or slice
array := [5]int{1, 2, 3, 4, 5}
slice := array[1:4] // [2, 3, 4]Slices have both a length and a capacity:
- Length: The number of elements the slice contains (
len(slice)) - Capacity: The number of elements in the underlying array (
cap(slice))
slice := make([]int, 3, 5)
fmt.Println(len(slice)) // 3
fmt.Println(cap(slice)) // 5The append function adds elements to the end of a slice and returns a new slice:
slice := []int{1, 2, 3}
slice = append(slice, 4) // [1, 2, 3, 4]
slice = append(slice, 5, 6, 7) // [1, 2, 3, 4, 5, 6, 7]
// Append one slice to another
other := []int{8, 9, 10}
slice = append(slice, other...) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]You can create a slice from a slice using the slicing operator:
slice := []int{1, 2, 3, 4, 5}
sub := slice[1:3] // [2, 3]The copy function copies elements from one slice to another:
src := []int{1, 2, 3}
dst := make([]int, len(src))
n := copy(dst, src) // n is number of elements copied (3)To find the maximum value in a slice of integers:
func findMax(numbers []int) int {
if len(numbers) == 0 {
return 0 // or another default value
}
max := numbers[0]
for _, n := range numbers[1:] {
if n > max {
max = n
}
}
return max
}To remove duplicates while preserving order:
func removeDuplicates(numbers []int) []int {
if len(numbers) == 0 {
return []int{}
}
// Use a map to track seen values
seen := make(map[int]bool)
result := make([]int, 0, len(numbers))
for _, n := range numbers {
if !seen[n] {
seen[n] = true
result = append(result, n)
}
}
return result
}To reverse the order of elements in a slice:
func reverseSlice(slice []int) []int {
result := make([]int, len(slice))
for i, v := range slice {
result[len(slice)-1-i] = v
}
return result
}
// Alternative approach that modifies the original slice
func reverseInPlace(slice []int) {
for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
slice[i], slice[j] = slice[j], slice[i]
}
}To filter elements based on a condition (e.g., keeping only even numbers):
func filterEven(numbers []int) []int {
result := make([]int, 0)
for _, n := range numbers {
if n%2 == 0 {
result = append(result, n)
}
}
return result
}Slices are references to arrays, so modifying a slice modifies the underlying array:
original := []int{1, 2, 3, 4, 5}
sub := original[1:3]
sub[0] = 42 // Modifies original too
fmt.Println(original) // [1, 42, 3, 4, 5]To create an independent copy of a slice:
original := []int{1, 2, 3, 4, 5}
copy := make([]int, len(original))
copy = append(copy, original...)For efficiency when building slices incrementally, pre-allocate with a capacity:
// Inefficient
var result []int
for i := 0; i < 10000; i++ {
result = append(result, i) // Many allocations and copies
}
// Efficient
result := make([]int, 0, 10000)
for i := 0; i < 10000; i++ {
result = append(result, i) // No reallocation needed
}An empty slice has length 0 but is not nil:
var nilSlice []int // nil, len 0, cap 0
emptySlice := []int{} // not nil, len 0, cap 0
emptyMake := make([]int, 0) // not nil, len 0, cap 0
fmt.Println(nilSlice == nil) // true
fmt.Println(emptySlice == nil) // false