DEV Community

Cover image for Let's Talk About Slices in Go: The Dynamic Duo of Arrays!
Bruno Ciccarino λ for learn go

Posted on

Let's Talk About Slices in Go: The Dynamic Duo of Arrays!

So, you're diving into Go and you hear about slices. “What even are slices?” you might wonder. Aren't arrays enough? Well, let’s break it down! Slices are a killer feature in Go. They’re like arrays, but way cooler — they’re dynamic and flexible, capable of growing and shrinking as your program needs. But there's a catch or two along the way. Let’s unpack it all and get you slice-savvy!

slices golang

Slices: Arrays on Steroids

At their core, slices are arrays. But unlike static arrays, slices are dynamic; they can change size, which is super handy when your data needs are unpredictable. Imagine you’ve got a list of items, and sometimes it’s 5 items, but other times it could be 50! Slices make that no big deal. They just resize themselves — kinda like magic. ✨

But here’s the deal: every time a slice changes size, a brand new array is created underneath it, and the data is copied over to this new array. Convenient? Definitely! But there’s a bit of a computational cost here. Every resize means Go has to allocate new memory and shuffle things around.

So, How Do We Tame This Beast? Enter make

Here’s a handy Go tip for ya: if you know you're going to need a lot of space for a slice, use the make function. With make([]T, len, cap), you’re telling Go: “Hey, give me a slice of this type, with this length, and this capacity.” Having an initial capacity ready to go saves you the cost of resizing later. Smart, right?

  • For example:
numbers := make([]int, 0, 100)
Enter fullscreen mode Exit fullscreen mode

This slice starts with a capacity of 100 but has no items in it yet. You’re ready to fill it up without Go constantly resizing things. In the long run, you save on performance.

Length vs. Capacity: The Dynamic Duo of Slices

Every slice has a length (len) and a capacity (cap), and they play different roles:

  • len(slice): This is the number of elements currently in the slice.
  • cap(slice): This is the maximum length the slice can hold before needing a resize. Let’s say you’ve got a slice x. If you try to access x[n] with an n that's greater than the length (len(x)), you'll get an out-of-range error. But, no worries! If you’re adding items to a slice and you hit its capacity, Go just allocates a bigger array for you under the hood. All you gotta do is keep coding.

Need to Add More Items? Meet append

When you want to grow a slice, append is your go-to function. It’s designed to add elements at the end of your slice, and it automatically resizes the slice if needed. Say goodbye to out-of-bounds errors (well, mostly)!

  • Here’s a practical example:
numbers := []int{1, 2, 3}
numbers = append(numbers, 4, 5, 6)
Enter fullscreen mode Exit fullscreen mode

If the slice has enough capacity to fit the new items, it’ll use it. If not, append creates a new array with more space and moves your data over. Simple as that! According to Effective Go, if the capacity is insufficient, append will "allocate a new underlying array." Pretty neat, right?

Wrapping Up

Slices in Go are your friend — and a powerful one at that. They let you work with collections of data flexibly, all while hiding some of the gritty details of memory management. But remember: with great power comes great responsibility. Every resize comes with a bit of computational overhead. By understanding how slices work and how make and append can help, you’re well on your way to writing efficient, elegant Go code.

effective-go

Top comments (2)

Collapse
 
jonasbn profile image
Jonas Brømsø

Thank you for a good article and nice visuals. I really like visual representations, so I can recommend this cheat sheet for slices.

Collapse
 
brunociccarino profile image
Bruno Ciccarino λ

Thank you for the feedback and recommendation