Go 1.21.0 `slices` package

Cheikh seck
3 min readJul 2, 2023

An article showcasing the Index and Replace functions from the slices package.

Image by Andra Ion via unsplash.

How many Gophers can say that they’ve never found themselves writing a function that loops over an array to determine the index of an element?

In my opinion, very few; with Go 1.21, this number may be reduced to zero. Go 1.21 features a package named slices — a package with a set of helper functions for slices. In this post, I’m going to demonstrate how the slices package can be leveraged to find the index of an element, regardless of its type, and remove it from the slice.

Requirements

The code in this post imports the slices package with import path slices; thus for the following code to work you will need Go 1.21.

Basic Example

As for the first use case, I’ll write a program that will look for a string within a slice, return its index and remove the string stored at said index from the slice. Prior to writing any code, I’ll list the functions I’ll be using to achieve this. (these functions are from the slices package.)

func Index[S ~[]E, E comparable](s S, v E) int

The Index function will return the index of an element within a given slice; this function will prevent me from writing another for loop to query an item. One of this function’s best qualities is that it is generic and I’m only limited by the comparable types I can use as a slice’s element type; I’ll further explore this in the next example. The next function I’d like to examine is the Replace function.

func Replace[S ~[]E, E any](s S, i, j int, v ...E) S

The Replace function is also generic and allows you to replace a slice of an array — this slice is constructed with parameters i and j— with the values passed as variadic parameter v. I’m going to pass no values and replace the specified slice with nothing; this will technically remove the specified element from the slice.

package main

import (
"fmt"

"slices"
)

func main() {

names := []string{"Alice", "Bob", "Vera", "Zac", "Zac2"}

aIndex := slices.Index(names, "Alice")

names = slices.Replace(names, aIndex, aIndex+1)
fmt.Printf("Value %v", names)

}

// Output
// Value [Bob Vera Zac Zac2]

The program displayed above will search for an entry named Alice and return its index; this index is then used to indicate which slice to replace within the array. Since no values to replace with were passed, the entry Alice will be removed from the list. What if the list has two entries named Alice?

Now, Why is this special?

One of my favorite Go features is the language semantics and how it offers a simple way to specify if a variable is a pointer or not. The following program will remove the second Alice value, deliberately.

package main

import (
"fmt"

"slices"
)

func main() {

alice1 := "Alice"
alice2 := "Alice"
vera := "Vera"
zac := "Zac"
namesPointer := []*string{
&alice1,
&zac,
&alice2,
&vera,
}

aIndex = slices.Index(namesPointer, &alice2)

namesPointer = slices.Replace(namesPointer, aIndex, aIndex+1)
fmt.Printf("Pointer %v [%v %v %v] ", namesPointer, *namesPointer[0], *namesPointer[1], *namesPointer[2])
}

// Output
// Pointer [0xc000096080 0xc0000960b0 0xc0000960a0] [Alice Zac Vera]

In the program above, I’m passing a pointer address of the second Alice in the array to the Index function; this will return the index of the pointer address, which will be 2 in this case. I’ll proceed as normal and call the Replace function to remove it from the slice. I’m displaying the pointers side by side with the values to showcase that the second Alice record was correctly removed.

Conclusion

I still have a lot of ground to cover with the slice package; it offers a neat set of functions that will save me, and you, hours lost writing functions that search and modify an array. Now, there are the performance implications of these functions which I have not looked at; there may be other implementations of these functionalities that simply perform better and you are free to choose the one that solves your business problem.

I didn’t go too wild with second example because I’m currently reading the Pointers section of the Ardan Labs Ultimate Go tour, and I’m learning more about the topic.

For types that aren’t comparable, and aren’t necessarily pointers, the slices` package features the IndexFunc` that enables you to pass a function to perform the comparison.

--

--