Cookies management by TermsFeed Cookie Consent
Russia has invaded Ukraine and already killed tens of thousands of civilians, with many more raped or tortured. It's a genocide. We need your help. Let's fight back against the Russian regime.
Help Ukraine! Fight the Russian regime!

💂 Filter a slice using Generics in Go

introduction generics generics-intro

Please consider supporting us by disabling your ad blocker

Until now, it was difficult to create in Go the filter() function known from functional programming, which filters any list of elements according to the boolean value of the predicate. It was possible if you knew the type of the list:

1
2
3
4
5
6
7
8
9
func filter(slice []string, f func(string) bool) []string {
    var n []string
    for _, e := range slice {
        if f(e) {
            n = append(n, e)
        }
    }
    return n
}

The main drawback of this solution was that you had to write a separate function for each slice type or use interface{} and type assertions.

However, with the release of Generics in Go 1.18, we got the ability to write functions where type is a parameter. So now there is no problem writing a filter() function that operates on a slice of any type.

This article is part of the Introduction to Go Generics series. Go here to see more.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
    "fmt"
    "strings"
)

func filter[T any](slice []T, f func(T) bool) []T {
    var n []T
    for _, e := range slice {
        if f(e) {
            n = append(n, e)
        }
    }
    return n
}

func main() {
    websites := []string{"http://foo.com", "https://bar.com", "https://gosamples.dev"}
    httpsWebsites := filter(websites, func(v string) bool {
        return strings.HasPrefix(v, "https://")
    })
    fmt.Println(httpsWebsites)

    numbers := []int{1, 2, 3, 4, 5, 6}
    divisibleBy2 := filter(numbers, func(v int) bool {
        return v % 2 == 0
    })
    fmt.Println(divisibleBy2)
}

Output:

[https://bar.com https://gosamples.dev]
[2 4 6]

The filter() function takes as an argument a slice of type T. The T type has the any constraint, and as you already know from our previous tutorial on Generics, this constraint means that there are no requirements on the type of the slice - it can be anything. The same type T is used as an argument to the predicate function that checks whether the value should be added to the result. The body of the filter() function is simple. It performs an iteration over the slice and adds to the result those elements that return true from the predicate function. As you can see in the output of the example, it works with slices of both string and int types, as well as any other type.

🗑️ Remove duplicates from any slice using Generics in Go

Learn how to create a slice with unique values using Generics
introduction slice generics generics-intro

🔉 Reduce function using Generics in Go

Learn how to define a function to accumulate slice values using Generics
introduction generics generics-intro

🦾 Create a slice 'map' function using Generics in Go

Learn how to apply a function to all slice elements using Generics
introduction generics generics-intro