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