Let's talk about Slices in Go
Last Update: Dec 26, 2022
I wrote a book! Check out A Quick Guide to Coding with AI.
Become a super programmer!
Learn how to use Generative AI coding tools as a force multiplier for your career.
Slices in Go can be awesome yet confusing at the same time. It’s a funky datatype for sure but extremely powerful once you get the hang of using them. Today we’re going to talk about what they are, why you would use a slice in Go, and some of the cool things you can do with them.
What is a Slice?
A slice is a data type in Go that points to an underlying array. Think of it as a “view” of an array. To appreciate what a slice does, you must know how an array works.
An array is a grouping of values of a particular type.
For instance:
var someints [10]int
This declares a group of 10 integers. You can add items in like so:
someints[1] = 33
Or you can initialize the array with values:
someints := [5]int{26, 44, 67, 12, 33}
They don’t have to be integers. You can have string arrays as well:
someints := [5]string{"Barts", "Yorkie", "Sholtzy", "Fisky", "Boomtown"}
And of course, each has an index and a value you can display:
Easy stuff.
So why don’t we use arrays for everything?
In Go programming, you will (and should) use arrays all the time. They’re screaming-fast data types and are great when you know precisely how many elements you need upfront.
This is one constraint of arrays. You must know upfront how much space you’ll need. When you create an array, space is allocated for your data, whether you use it or not.
For instance, this works:
someints := [10]string{"Barts", "Yorkie", "Sholtzy", "Fisky", "Boomtown"}
Now you’ll notice your array has ten elements in it:
The length of the array is 10, no matter what data is inside.
You can add to that array:
someints[5] = "Jonesy"
And it will add to your list.
However, you’re restricted to the ten elements you declared in your array. If you try to do this:
someints[15] = "Shoresy"
You’ll get an error:
It’s not a big deal. You can always recreate a new array with more elements and transfer the contents of the existing array into the new one.
But, slices do this for you. Hence the reason we’d want to use them. Let’s take a look.
How to use Slices
Using a slice is almost identical to an array. However, a slice becomes a dynamically typed array.
Let’s look at the array we just created. We’ll check the length of the array:
fmt.Printf("Length of someints: %v\n", len(someints))
That tells us the length is ten, but we only have five names in there. So let’s change it to a slice.
someints := []string{"Barts", "Yorkie", "Sholtzy", "Fisky", "Boomtown"}
There isn’t much of a difference in syntax or the way we use it. But now, when we display it:
That’s an accurate length.
Plus, we can add as many elements as we want to it:
someints = append(someints, "Jonesy", "Shoresy", "Wayne", "Katy")
And our slice has grown to accommodate the new values:
And I just noticed, that I still have the slice named someints
though they’re not integers.
We can add and subtract elements at will without having to create a new array. As the slice changes, the compiler automatically creates and recreates the underlying array for you.
So think of a slice as a dynamically sized array
But that’s not all!
It’s fun to work with slices. You can even make with a slice of a slice.
So if I create a slice like this:
chirpers := []string{"Barts", "Yorkie", "Sholtzy", "Fisky", "Boomtown"}
I can select any element directly:
fmt.Println(chirpers[2])
Or a slice of elements. You can select the starting element and ending element of the array:
with slicename[ starting index ][ ending index ]
fmt.Println(chirpers[2:5])
Of you want to select the beginning or end of the slice as a starting point or ending point, you can omit that value:
fmt.Println(chirpers[:5])
You can use it to get the last element of the slice (after all, it is dynamic):
fmt.Println(chirpers[(len(chirpers) - 1):])
Adding to a Slice
Adding elements to a slice is easy:
chirpers = append(chirpers, "Shoresy")
We can use append to add on as many elements as we want.
Removing an Element from a Slice
There are no built-in functions in Go to remove an element from a slice.
But you can use append to shift the values for a particular element, so that the element you want to remove gets replaced with the next value in the slice.
Let’s say we want to remove Fisky (at element 3):
chirpers = append(chirpers[:3], chirpers[4:]...)
Here we are appending element three onward with element four and the values after it.
It’s essentially just shifting all the values over one element. This may seem clunky and will have a performance cost, but it helps to remember there is still an array backing this slice.
Conclusion: Slices are great! Most of the time
So we’ve looked at slices and learned how they are essentially a “view” of an array. They’re helpful for when you need a dynamically sized array or if you want to extract specific parts of an array easily.
I’ve just scratched the surface of slices and what you can do with them. I’ve used them all over the place, and they’re very handy. The extra abstraction does have a difference in performance, but it’s minimal most of the time.
If you’d like to learn more about slices, arrays, or Go in general, Check this out. It’s an excellent explanation of how they work together.
You can also test your current Go skills and see where you rank.
Thanks for reading!
Want to become an expert Go programmer?
You can boost your skills in a few weekends by taking these high quality Go courses taught by top experts!
We have over 30 hours of Go courses you can take now! You can try it for 10 days free of charge.