Arrays vs Slice in Go

Arrays vs Slice in Go

September 26, 2023 | 4 mins read.

Arrays and slices are fundamental data structures in the Go programming language, each with its own set of characteristics and use cases. Understanding the differences between them is essential for writing efficient and flexible Go code. In this blog post, we will explore the distinctions between arrays and slices, when to use each, and practical examples to illustrate their roles in Go programming.

Arrays in Go

An array in Go is a fixed-size collection of elements of the same data type. Once you define an array with a specific size, you cannot change its size during runtime. Here’s how you declare an array:

var numbers [5]int

In this example, we’ve declared an array named numbers that can hold five integers. Arrays are zero-indexed, meaning the first element is accessed using numbers[0], the second with numbers[1], and so on.

Use Cases for Arrays

Arrays are suitable for scenarios where you know the exact number of elements you need, and that number won’t change during the program’s execution. Common use cases for arrays include:

Storing a fixed number of items like days of the week or months of the year. Maintaining a history of recent values with a circular buffer. Representing mathematical vectors with a fixed dimension.

Slices in Go

Slices, on the other hand, are dynamic and flexible data structures in Go. They are references to underlying arrays and can grow or shrink as needed. To declare a slice, you don’t specify its size, as it is managed automatically by Go:

var names []string // Declaration of a slice
names = append(names, "Alice")

In this example, we’ve declared a slice named names that can store strings. The append function is used to add elements to the slice dynamically. Slices allow you to work with variable-length collections of data.

Use Cases for Slices

Slices are particularly useful when you need a dynamically resizable collection of elements. Common use cases for slices include:

Managing lists, queues, or stacks where the size can change.
Reading and manipulating data from files, databases, or network streams.
Creating sub-slices to work with specific portions of a larger dataset.

Key Differences Between Arrays and Slices

Fixed Size vs. Dynamic Size

Arrays have a fixed size determined at declaration, and it cannot change during runtime. Slices are dynamic and can grow or shrink as elements are added or removed.

Initialization

Arrays must be initialized with their size and can be initialized with zero values for their data type. Slices do not require explicit size specification, and they can be initialized using literals or the make function.

Passing by Value vs. Passing by Reference

Arrays are passed by value when assigned to other variables or passed as function arguments, resulting in a copy of the array. Slices are passed by reference, meaning they point to the same underlying array. Modifying a slice affects the original data.

Length and Capacity

Arrays have a fixed length defined at creation, which is always the same as the array’s capacity. Slices have both a length (the number of elements it contains) and a capacity (the maximum number of elements it can hold without reallocation).

Practical Examples

Let’s look at some practical examples to illustrate the differences:

Storing Data

If you need to store a fixed number of temperatures for a week, you might use an array:


var temperatures [7]float64
temperatures[0] = 72.5
// ...

However, if you want to store temperatures for an arbitrary number of days, a slice is a better choice:


temperatures := []float64{72.5, 73.2, 71.8}

Modifying Data

When modifying elements in an array, a copy is created:


array := [3]int{1, 2, 3}
modifiedArray := array
modifiedArray[0] = 42 // Does not affect the original array

With slices, changes affect the original data:


slice := []int{1, 2, 3}
modifiedSlice := slice
modifiedSlice[0] = 42 // Affects the original slice

Conclusion

Arrays and slices are both essential data structures in Go, but they serve different purposes. Arrays are suitable for fixed-size collections, while slices offer the flexibility of dynamic sizing. Understanding when to use each data structure is crucial for writing efficient and maintainable Go code. Choose the one that best fits your specific use case to harness the full power of Go’s data structures.