Menu
Coddy logo textTech

sort.Interface

Part of the Object Oriented Programming section of Coddy's GO journey — lesson 74 of 107.

The sort package provides another excellent example of interface-based design. To sort a custom collection, your type must implement the sort.Interface:

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

These three methods give the sort algorithm everything it needs: the collection's length, a way to compare elements, and a way to swap them. Here's how to make a slice of custom structs sortable:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

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

func main() {
    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Carol", 35},
    }
    
    sort.Sort(ByAge(people))
    fmt.Println(people)
    // [{Bob 25} {Alice 30} {Carol 35}]
}

The key insight is creating a named type (ByAge) based on your slice. This lets you define different sorting behaviors for the same data. You could create ByName with a different Less implementation to sort alphabetically instead.

Once your type satisfies sort.Interface, it works with sort.Sort(), sort.Reverse(), and sort.IsSorted() automatically.

challenge icon

Challenge

Easy

Let's build a sortable product inventory system that demonstrates the power of Go's sort.Interface! You'll create a Product type and implement multiple sorting strategies, allowing the same collection to be sorted in different ways.

You'll organize your code across two files:

  • product.go: Define your product type and sorting implementations.

    Create a Product struct with three fields: Name (string), Price (float64), and Quantity (int).

    Create two named types based on []Product:

    • ByPrice - for sorting products by price in ascending order
    • ByQuantity - for sorting products by quantity in descending order (highest quantity first)

    Each type needs to implement the three methods required by sort.Interface: Len(), Less(i, j int), and Swap(i, j int). The Less method determines the sort order for each type.

  • main.go: Build and sort your product inventory.

    Read a sort mode (price or quantity), then read a count followed by product details. Each product is provided as three lines: name, price, and quantity.

    Create a slice of products, sort them using the appropriate sorting type based on the mode, then print each product in this format:

    [Name]: $[Price] (x[Quantity])

    Display prices with two decimal places.

The following inputs will be provided:

  • Line 1: Sort mode (price or quantity)
  • Line 2: Number of products
  • Following lines: Product details (name, price, quantity - three lines per product)

For example, given:

price
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

Your output should be:

Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)

And given:

quantity
3
Laptop
999.99
5
Mouse
29.99
50
Keyboard
79.99
25

Your output should be:

Mouse: $29.99 (x50)
Keyboard: $79.99 (x25)
Laptop: $999.99 (x5)

Notice how the same product data can be sorted differently by simply using a different named type. Once your types satisfy sort.Interface, they work seamlessly with sort.Sort() from the standard library.

Cheat sheet

The sort package requires types to implement the sort.Interface to be sortable:

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

To make a custom slice sortable, create a named type and implement the three required methods:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

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

// Sort the collection
sort.Sort(ByAge(people))

You can create multiple named types for the same slice to implement different sorting behaviors. Each type defines its own Less method to determine sort order.

Once a type satisfies sort.Interface, it works with sort.Sort(), sort.Reverse(), and sort.IsSorted().

Try it yourself

package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Read sort mode
	var mode string
	fmt.Fscanln(reader, &mode)

	// Read number of products
	var count int
	fmt.Fscanln(reader, &count)

	// Read products
	products := make([]Product, count)
	for i := 0; i < count; i++ {
		name, _ := reader.ReadString('\n')
		name = name[:len(name)-1] // Remove newline

		priceStr, _ := reader.ReadString('\n')
		priceStr = priceStr[:len(priceStr)-1]
		price, _ := strconv.ParseFloat(priceStr, 64)

		qtyStr, _ := reader.ReadString('\n')
		qtyStr = qtyStr[:len(qtyStr)-1]
		quantity, _ := strconv.Atoi(qtyStr)

		products[i] = Product{Name: name, Price: price, Quantity: quantity}
	}

	// TODO: Sort products based on mode
	// If mode is "price", use ByPrice type
	// If mode is "quantity", use ByQuantity type
	// Use sort.Sort() with the appropriate type

	// TODO: Print each product in the format:
	// [Name]: $[Price] (x[Quantity])
	// Use fmt.Printf with %.2f for price formatting
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming