Go Slices
What is a Slice in Go?
A slice in Go is a dynamically-sized, more flexible abstraction over an array. Unlike arrays, slices do not have a fixed length, making them more suitable for working with collections of data. Slices provide built-in functionalities for resizing, appending, and copying elements efficiently.
Syntax of a Slice
A slice is declared using the following syntax:
var sliceName []Type // Declaring a slice without initialization
sliceName := []Type{element1, element2, element3} // Declaring and initializing a slice
Creating Slices
1. Declaring a Slice Without Initialization
var numbers []int // Declares a slice of integers fmt.Println(numbers) // Output: []
Here, numbers is declared as a slice of integers but is not yet initialized. It has nil value by default.
2. Initializing a Slice with Values
fruits := []string{"Apple", "Banana", "Cherry"} fmt.Println(fruits) // Output: [Apple Banana Cherry]
This slice is initialized with three string elements.
3. Using the make Function
The make function allows creating slices with a specified length and capacity.
slice := make([]int, 3, 5) fmt.Println(slice) // Output: [0 0 0] fmt.Println(len(slice)) // Output: 3 (length) fmt.Println(cap(slice)) // Output: 5 (capacity)
- The slice has an initial length of 3 and a capacity of 5.
- Extra capacity can be used when appending elements.
Accessing and Modifying Slices
You can access slice elements using an index, just like arrays.
nums := []int{10, 20, 30, 40} fmt.Println(nums[1]) // Output: 20 nums[2] = 50 // Modifying an element fmt.Println(nums) // Output: [10 20 50 40]
Here, nums[2] was updated from 30 to 50.
Slicing an Existing Slice
A slice can be created from another slice using the slicing operation:
original := []int{1, 2, 3, 4, 5} subSlice := original[1:4] // Extracts elements from index 1 to 3 (excluding index 4) fmt.Println(subSlice) // Output: [2 3 4]
- original[1:4] extracts elements starting from index 1 up to, but not including, index 4.
Omitting Start or End Index
fmt.Println(original[:3]) // Output: [1 2 3] (from start to index 2) fmt.Println(original[2:]) // Output: [3 4 5] (from index 2 to the end) fmt.Println(original[:]) // Output: [1 2 3 4 5] (entire slice)
Appending to a Slice
Go provides the append function to add elements to a slice dynamically.
nums := []int{1, 2, 3} nums = append(nums, 4, 5) fmt.Println(nums) // Output: [1 2 3 4 5]
If the slice reaches its capacity, a new underlying array is allocated.
Appending One Slice to Another
slice1 := []int{1, 2} slice2 := []int{3, 4} combined := append(slice1, slice2...) // Using `...` to unpack slice2 fmt.Println(combined) // Output: [1 2 3 4]
Copying a Slice
The copy function is used to copy one slice into another.
source := []int{10, 20, 30} destination := make([]int, len(source)) copy(destination, source) fmt.Println(destination) // Output: [10 20 30]
- The destination slice must have enough space to hold copied elements.
Slice Capacity and Growth
When appending elements, if the capacity is exceeded, Go automatically allocates a new, larger array.
numbers := []int{1, 2, 3} fmt.Println(cap(numbers)) // Initial capacity numbers = append(numbers, 4, 5, 6) fmt.Println(cap(numbers)) // Capacity might increase dynamically
Iterating Over a Slice
Use a for loop or range to traverse elements.
Using for Loop
nums := []int{10, 20, 30} for i := 0; i < len(nums); i++ { fmt.Println(nums[i]) }
Using range Loop
fruits := []string{"Mango", "Orange", "Grape"} for index, value := range fruits { fmt.Println(index, value) } // Output: // 0 Mango // 1 Orange // 2 Grape
- The index variable holds the current position.
- The value variable holds the element.
Nil and Empty Slices
A slice declared without initialization is nil.
var emptySlice []int fmt.Println(emptySlice == nil) // Output: true
An empty slice can also be initialized explicitly.
empty := []int{} fmt.Println(empty) // Output: [] fmt.Println(len(empty)) // Output: 0
Multi-Dimensional Slices
Slices can contain other slices, forming a multi-dimensional structure.
matrix := [][]int{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, } fmt.Println(matrix[1][2]) // Output: 6
Each row can have different lengths, making it a jagged slice.
Conclusion
Slices in Go provide a flexible and efficient way to work with lists of data. They support dynamic resizing, slicing, appending, and copying operations. Understanding slices is crucial for optimizing performance and memory usage in Go applications.
PreviousNext