Sling Academy
Home/Golang/Filtering composite types in a slice in Go

Filtering composite types in a slice in Go

Last updated: November 21, 2024

Filtering slices is a common operation in Go, especially when dealing with collections of data structures or composite types. In Go, a composite type is one that is made up of several types, such as structs, arrays, or slices themselves. This article will guide you through the process of filtering composite types specifically within a slice, starting from basic to more advanced examples.

Basic Example: Filtering a Slice of Integers

Before we dive into composite types, it’s helpful to understand how filtering works in simpler scenarios, like filtering a slice of integers. Filters remove elements that do not meet specific criteria, producing a new slice.

package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6}
    evenNumbers := filter(numbers, func(n int) bool {
        return n%2 == 0
    })
    fmt.Println(evenNumbers) // Output: [2, 4, 6]
}

func filter(nums []int, test func(int) bool) []int {
    var result []int
    for _, v := range nums {
        if test(v) {
            result = append(result, v)
        }
    }
    return result
}

Intermediate Example: Filtering a Slice of Structs

In real-world applications, data is often stored in custom structs. Here’s how to filter a slice of structs based on one or more struct fields.

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Charlie", 35},
    }
    filteredPeople := filterPeople(people, func(p Person) bool {
        return p.Age > 30
    })
    fmt.Println(filteredPeople) // Output: [{Charlie 35}]
}

func filterPeople(people []Person, test func(Person) bool) []Person {
    var result []Person
    for _, p := range people {
        if test(p) {
            result = append(result, p)
        }
    }
    return result
}

Advanced Example: Using Generics for Slice Filtering

With the introduction of generics in Go 1.18, we can write more abstract and reusable filter functions that work for different types.

package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6}
    evenNumbers := genericFilter(numbers, func(n int) bool {
        return n%2 == 0
    })
    fmt.Println(evenNumbers) // Output: [2, 4, 6]

    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Charlie", 35},
    }
    filteredPeople := genericFilter(people, func(p Person) bool {
        return p.Age > 30
    })
    fmt.Println(filteredPeople) // Output: [{Charlie 35}]
}

type Person struct {
    Name string
    Age  int
}

func genericFilter[T any](slice []T, test func(T) bool) []T {
    var result []T
    for _, v := range slice {
        if test(v) {
            result = append(result, v)
        }
    }
    return result
}

Generics allow for a cleaner and more versatile filtering approach, letting you reuse `genericFilter` for any type without rewriting the function for each new use case.

Next Article: Calculate the sum and average of a numeric slice in Go

Previous Article: How to filter strings in a slice in Go

Series: Working with Slices in Go

Golang

Related Articles

You May Also Like

  • How to remove HTML tags in a string in Go
  • How to remove special characters in a string in Go
  • How to remove consecutive whitespace in a string in Go
  • How to count words and characters in a string in Go
  • Relative imports in Go: Tutorial & Examples
  • How to run Python code with Go
  • How to generate slug from title in Go
  • How to create an XML sitemap in Go
  • How to redirect in Go (301, 302, etc)
  • Using Go with MongoDB: CRUD example
  • Auto deploy Go apps with CI/ CD and GitHub Actions
  • Fixing Go error: method redeclared with different receiver type
  • Fixing Go error: copy argument must have slice type
  • Fixing Go error: attempted to use nil slice
  • Fixing Go error: assignment to constant variable
  • Fixing Go error: cannot compare X (type Y) with Z (type W)
  • Fixing Go error: method has pointer receiver, not called with pointer
  • Fixing Go error: assignment mismatch: X variables but Y values
  • Fixing Go error: array index must be non-negative integer constant