Arrays, Slices and, Maps
In Go, arrays, slices, and maps are built-in types used for storing and working with collections of data. Each of these data structures serves a different purpose and has its own unique characteristics and use cases. Understanding how they work helps me write more efficient and effective Go code.
Arrays in Go
An array in Go is a fixed-size, ordered collection of elements of the same type. The length of an array is part of its type, meaning that arrays with different lengths are considered different types.
Key Characteristics of Arrays
- Fixed Size: The size of an array is defined at the time of its declaration and cannot be changed.
- Homogeneous: All elements in an array must be of the same type (e.g., all integers, all strings).
- Memory Allocation: Arrays are stored in contiguous blocks of memory.
Declaring an Array
To declare an array in Go, we specify the type of the elements followed by the length of the array.
var arr [5]int // An array of 5 integers
We can also initialize the array at the time of declaration:
var arr = [3]int{1, 2, 3}
Alternatively, Go allows us to omit the size and let the compiler infer it:
arr := [...]int{1, 2, 3} // The compiler infers the size (3)
Accessing Elements
We can access elements of an array using an index (starting from 0):
arr[0] = 10 // Set the first element to 10
fmt.Println(arr[0]) // Get the first element
Arrays and Memory
When we pass an array to a function, Go passes the entire array by value (copying the array), so modifying the array inside the function will not affect the original array outside the function. To modify an array inside a function, we would need to pass a pointer to the array.
Example:
func modifyArray(arr [3]int) {
arr[0] = 99
}
func main() {
arr := [3]int{1, 2, 3}
modifyArray(arr)
fmt.Println(arr) // Output: [1 2 3]
}
Array Length
We can get the length of an array using the built-in len()
function.
fmt.Println(len(arr)) // Output: 3
Slices in Go
A slice is a more flexible, dynamic view into an array. Unlike arrays, slices can grow and shrink in size as needed. Slices are a more common data structure in Go, and they provide powerful capabilities to work with sequences of data.
Key Characteristics of Slices
- Dynamic Size: Unlike arrays, slices do not have a fixed size. We can append elements, and their size can grow or shrink.
- Reference Type: Slices are reference types, meaning they point to an underlying array. When we pass a slice to a function, the function can modify the contents of the slice.
- Literals: A slice is created using a range of elements from an existing array or using the
make()
function.
Declaring a Slice
Slices are typically declared in one of two ways:
-
Using an array literal:
slice := []int{1, 2, 3, 4} // Slice with initial elements
-
Using
make()
function:slice := make([]int, 5) // Creates a slice of length 5 with default values (zeros)
We can also create a slice with a specific capacity:
slice := make([]int, 5, 10) // Slice with length 5 and capacity 10
Accessing and Modifying Elements
Just like arrays, we access and modify elements in a slice using indices:
slice[0] = 10 // Modify the first element
fmt.Println(slice[0]) // Get the first element
Slicing a Slice
We can create a sub-slice by specifying a range:
s := []int{1, 2, 3, 4, 5}
subSlice := s[1:4] // Slice from index 1 to 3 (not including 4)
fmt.Println(subSlice) // Output: [2 3 4]
Appending to a Slice
The append()
function is used to add elements to a slice. This function returns a new slice with the added elements.
s := []int{1, 2, 3}
s = append(s, 4) // Adds 4 to the slice
fmt.Println(s) // Output: [1 2 3 4]
If the slice's underlying array is full (i.e., the slice has reached its capacity), Go automatically allocates a new, larger array to accommodate the new elements.
Passing Slices to Functions
Slices are reference types, so when passed to a function, the function can modify the underlying array directly.
func modifySlice(s []int) {
s[0] = 99
}
func main() {
slice := []int{1, 2, 3}
modifySlice(slice)
fmt.Println(slice) // Output: [99 2 3]
}
Length and Capacity
- Length: The number of elements in the slice (
len()
). - Capacity: The number of elements the slice can accommodate before it needs to be resized (
cap()
).
fmt.Println(len(slice)) // Length
fmt.Println(cap(slice)) // Capacity