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:

“Golang Slices how to”

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:

“Golang Slices how to”

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.

“Golang Slices how to”

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:

“Golang Slices how to”

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))

“Golang Slices how to”

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:

“Golang Slices how to”

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:

“Golang Slices how to”

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])

“Golang Slices how to”

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])

“Golang Slices how to”

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])

“Golang Slices how to”

You can use it to get the last element of the slice (after all, it is dynamic):

fmt.Println(chirpers[(len(chirpers) - 1):])

“Golang Slices how to”

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.

“Golang Slices how to”

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.

“Golang Slices how to”

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!





Learn how to leverage the Standard Library like a PRO. I just created a new course, The Go Standard Library, check it out!
Go Tutorials

Published: Sep 15, 2021 by Jeremy Morgan. Contact me before republishing this content.