Sling Academy
Home/Golang/How to sort custom types in a slice in Go (advanced)

How to sort custom types in a slice in Go (advanced)

Last updated: November 21, 2024

Sorting is a fundamental task in programming, and Go provides excellent tools for sorting built-in types. However, when working with custom types, the process requires a good understanding of Go interfaces, particularly the sort.Interface. This article will guide you through sorting custom types using Go's sort package with step-by-step instructions and examples.

Basic Sort with Primitive Types

Before diving into custom types, let’s start with sorting a slice of primitive types like int or string. Go’s sort package offers functions such as sort.Ints() and sort.Strings() for sorting slices of integers and strings, respectively.

package main

import (
    "fmt"
    "sort"
)

func main() {
    // Slice of integers
    nums := []int{5, 2, 6, 3, 1, 4}
    sort.Ints(nums)
    fmt.Println("Sorted ints:", nums) // Output: [1 2 3 4 5 6]

    // Slice of strings
    strs := []string{"banana", "apple", "orange"}
    sort.Strings(strs)
    fmt.Println("Sorted strings:", strs) // Output: ["apple" "banana" "orange"]
}

Sorting Custom Types

To sort a slice of a custom type, you need to implement the sort.Interface which requires three methods: Len(), Less(i, j int), and Swap(i, j int).

Intermediate Example: Sort by a Single Field

Suppose you have a Person struct with fields like Name and Age. You can sort a slice of Person by either field.

package main

import (
    "fmt"
    "sort"
)

// Defining the Person structure
type Person struct {
    Name string
    Age  int
}

// ByAge implements sort.Interface for []Person based on the Age field.
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

func main() {
    people := []Person{
        {Name: "Alice", Age: 25},
        {Name: "Bob", Age: 22},
        {Name: "Charlie", Age: 30},
    }

    sort.Sort(ByAge(people))
    fmt.Println("Sorted by age:", people) // Output: [{Bob 22} {Alice 25} {Charlie 30}]
}

Advanced Example: Sort by Multiple Criteria

In a more advanced case, you might need to sort by multiple fields, such as ordering by Age and in case of ties, sorting by Name.

package main

import (
    "fmt"
    "sort"
)

// Custom sorting by multiple criteria
type ByAgeAndName []Person

func (a ByAgeAndName) Len() int      { return len(a) }
func (a ByAgeAndName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAgeAndName) Less(i, j int) bool {
    if a[i].Age == a[j].Age {
        return a[i].Name < a[j].Name
    }
    return a[i].Age < a[j].Age
}

func main() {
    people := []Person{
        {Name: "Alice", Age: 25},
        {Name: "Bob", Age: 22},
        {Name: "Charlie", Age: 30},
        {Name: "David", Age: 22},
    }

    sort.Sort(ByAgeAndName(people))
    fmt.Println("Sorted by age, then name:", people) // Output: [{Bob 22} {David 22} {Alice 25} {Charlie 30}]
}

Conclusion

Sorting custom types in Go involves implementing the sort.Interface, which empowers you to define how the sorting logic should apply to your types. This approach forms the basis for leveraging Go's powerful standard library functions to manage complex data with ease.

Next Article: Filtering numbers in a slice in Go

Previous Article: Sorting a slice of strings 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