
Golang slices are a fundamental data structure in the Go programming language, and understanding their basics is crucial for efficient coding.
A Golang slice is a dynamically-sized, flexible view into an underlying array.
Slices are initialized using the `make` function, which allocates memory for the underlying array.
Golang slices are zero-indexed, meaning the first element is at index 0.
See what others are reading: Golang Copy Array
Syntax
A slice in Go can be declared in a simple way, like this:
To initialize the slice during declaration, use this:
The code above declares a slice of integers of length 3 and also the capacity of 3.
A slice has two important functions: len() and cap(). The len() function returns the length of the slice, which is the number of elements in the slice. The cap() function returns the capacity of the slice, which is the number of elements the slice can grow or shrink to.
A unique perspective: Golang Function Type
Array to List Conversion
Converting an array to a slice is straightforward. You can create a slice by slicing an array, as we saw in the example where myslice was created from arr1.
A slice can be created from any part of an array, not just the beginning. In the example, myslice started from the third element of arr1, which has value 12.
The length of the slice is determined by the starting index and the array it's created from. myslice has a length of 2, which is less than the length of arr1.
The capacity of a slice is the maximum number of elements it can hold without needing to reallocate memory. If myslice started from the first element of arr1, its capacity would be 6, which is the same as the length of arr1.
Slice Basics
A slice in Go is a reference to an array, and it's a fundamental data structure in the language. You can create a slice using a slice literal, which is similar to an array literal, but without specifying the size.
To create a slice using a slice literal, you can use the following syntax: `[]type{elements}`. For example, `[]int{1, 2, 3}` creates a slice of integers with the values 1, 2, and 3.
For your interest: Gcloud Api Using Golang
You can also create a slice from an existing array, which is useful when you want to work with a subset of the array's elements. The syntax for this is `array[start:end]`, where `start` is the index of the first element to include and `end` is the index of the last element to include.
Here's an example: `arr := [3]int{1, 2, 3}; slice := arr[1:2]` creates a slice with the value 2.
Another way to create a slice is by using the `make()` function, which takes three parameters: `type`, `length`, and `capacity`. The `capacity` parameter is optional and defaults to the `length` if not specified.
Note that the `make()` function is often used to create an empty slice, which is a slice that contains an empty array reference.
Here are the three ways to create a slice:
- Using a slice literal: `[]type{elements}`
- Using an existing array: `array[start:end]`
- Using the `make()` function: `make(type, length, capacity)`
Adding Elements
You can add elements to a slice in Go using the append function.
The append function appends elements to an existing slice, giving us dynamic array functionality.
You can use append to add elements to a slice like this: append(s, 42).
This will output: [42 0 0] because s was initialized to [0, 0, 0] with make([]int, 3) and then we appended 42 to that list.
Be careful when you use append to add elements to a list: do you want to start from index 0 or append them to the rest of the list?
As you add elements with append, you will eventually reach the end limit of the backing array.
When len equals cap, a new array will be allocated with a size double the previous capacity, and the pointer of the slice will point to the new allocated array.
After a certain number of elements, append will not double but grow with a lesser factor, and cap comes into play to tell append when it should allocate a new array for the slice.
Check this out: Golang Use .env File
Example Usage
You can create slices without specifying elements, resulting in a slice with a length and capacity of zero. This can be achieved using the []datatype{values} format.
To create a slice with elements, you can use the make function, specifying the length and capacity of the slice. For example, make([]string, 3) creates a slice of strings with a length and capacity of 3.
Slices can be modified using the append function, which returns a new slice containing one or more new values. This function can be used to add elements to the end of a slice.
Here are some examples of how to use the append function:
Slices can also be copied using the copy function, which copies elements from one slice to another. This can be useful when you need to create a new slice that is identical to an existing slice.
In addition to these basic operations, slices support several other functions that make them richer than arrays. One of these functions is the slice operator, which allows you to extract a subset of elements from a slice. This can be achieved using the syntax slice[low:high].
For example, s[2:5] extracts a slice containing the elements s[2], s[3], and s[4].
Discover more: How to Update a Github Using Golang
Iterating and Checking
Iterating over a Go slice can be done in a few ways. You can use a for loop, which is the simplest method.
To iterate over a slice using a for loop, you can get the index and the element value. This can be useful for tasks that require both the position and value of each element.
Here are some ways to iterate over a slice using a for loop:
Iterating Over a List
Iterating over a list is a fundamental concept in programming, and there are several ways to do it. You can use a for loop, which is the simplest way to iterate over a list.
For example, you can use a for loop to iterate over a slice, as shown in the article section "Example 1". This method is straightforward and easy to understand.
Using range in a for loop is another way to iterate over a list. This method allows you to get the index and the element value, which can be useful in certain situations. For instance, if you need to perform an operation on each element in the list, you can use the index to keep track of the current position.
For more insights, see: Create a List of Structs Golang
Here are the different ways to iterate over a list:
- Using a for loop with a range
- Using a blank identifier in a for loop
Using a blank identifier in a for loop is useful when you don't need to know the index of the elements. This can make your code more concise and easier to read. For example, you can use a blank identifier in a for loop to iterate over a slice without getting the index value.
Checking for Empty
Always use the len function to test if a slice is empty, as checking for nil can have unintended effects.
You might be tempted to check for nil, but it's better to use len to avoid surprises like the one shown in the example.
Using len ensures you get the correct result, whether the slice is empty or not.
Checking for nil can lead to false negatives, making it a less reliable approach.
In the example, checking for nil resulted in an empty slice being reported as not empty, which can cause problems in your code.
You might enjoy: Golang Use Cases
Important Points
A zero value slice in Go is a nil slice that doesn't contain any elements, with a capacity and length of 0.
Modifying a slice can be tricky because it's a reference type, meaning changes made to the slice will also affect the underlying array.
You can't compare slices using the == operator, but you can use the range for loop to match each element or the DeepEqual function instead.
Worth a look: T Golang
Why Capacity Matters
Capacity matters because it allows you to pre-allocate the internal array when creating a list, avoiding extra allocations.
This can be especially useful when you know in advance the number of elements you'll be inserting. By setting the capacity, you can allocate the right amount of space upfront, reducing the number of times the array needs to be resized.
For example, if you're creating a list that will hold 1000 elements, setting the capacity to 1000 will ensure that only one allocation is made, rather than allowing the array to grow and shrink as elements are added.

This approach can save time and improve performance, especially in scenarios where memory allocation is a concern.
By setting the capacity, you can also avoid the need for repeated allocations when creating a list from another list. This can be done by creating a slice with a length of 0 and a capacity equal to the desired size.
In this case, the slice will have space for the desired number of elements, and appending to it will not require any additional allocations.
For instance, if you create a slice with a length of 0 and a capacity of 2, the slice will be empty but its backing array will have space for 2 elements.
Important Points
You can create a nil slice in Go language that doesn't contain any elements. This type of slice has a length and capacity of 0.
Modifying a slice can be tricky because it's a reference type that can refer to an underlying array. If you change elements in the slice, the changes will also take place in the referenced array.

You can't compare two slices using the == operator, it will give you an error. Instead, use a range for loop to match each element or the DeepEqual function.
Multi-dimensional slices are similar to multidimensional arrays, but they don't contain their size. Sorting slices is also possible in Go language, using the sort package from the standard library.
Slice Growth and Allocation
A slice's capacity is the maximum number of elements it can hold before it needs to grow. By default, if you don't specify the third parameter in the slicing operation, the capacity is taken from the sliced slice or the length of the sliced array.
The capacity of a slice is not the same as the length of the underlying array. In fact, the capacity is the maximum number of elements the slice can hold before it needs to grow, which can be different from the length of the underlying array.
Go automatically creates a larger array, copies the elements over, and uses that new array as the slice's underlying array when the slice exceeds its current capacity. This is what happens when you keep adding elements to a slice and it surpasses its current capacity.
The growth rate of a slice's capacity is initially fast, doubling with each append operation. However, once the slice reaches a certain size, typically around 256, the growth slows down to 1.25 times the old capacity plus 192. This formula keeps the slice growing efficiently without wasting too much memory.
Here's a rough idea of how capacity grows from 0, depending on the type of slice:
How Grows
The capacity of a slice is the maximum number of elements it can hold before it needs to grow. Go will automatically create a larger array, copy the elements over, and use that new array as the slice's underlying array when the slice exceeds its current capacity.
By default, if you don't specify the third parameter in the slicing operation, the capacity is taken from the sliced slice or the length of the sliced array. This means that the capacity of a slice can be set to go up to a specific index of the original array.
Go adjusts the growth rate once the slice reaches a certain size, typically around 256. At this point, the growth slows down, following a formula that equates to 1.25 * oldCap + 192.
This method works as long as the new length does not exceed the slice's capacity. If you keep adding elements to a slice and it surpasses its current capacity, Go will automatically create a larger array and use that new array as the slice's underlying array.
A table shows how capacity grows from 0 for different types of slices:
Doubling capacity indefinitely would lead to huge memory allocations as the slice gets larger.
How Is Allocated
In the context of slice growth, allocation is a crucial step that determines how resources are distributed among different slices.
A slice's allocation is directly tied to its growth rate, as seen in the comparison of slice A and slice B, where slice A's 20% growth rate led to a 10% allocation increase.
The allocation process is also influenced by the slice's age, with younger slices typically receiving a larger allocation to support their growth.
In the example of slice C, its 5% allocation was adjusted downward due to its slower growth rate compared to other slices.
The allocation is also based on the slice's current size, with larger slices receiving a smaller allocation percentage.
Curious to learn more? Check out: Golang Copy Slice
Featured Images: pexels.com

