Lesson 4
Custom Sorting in Go
Topic Overview

Welcome to Custom Sorting in Go. In this lesson, we'll explore how to use slices and the sort package in Go to organize data structures with custom sorting mechanisms. By applying custom sorting functions, we can enhance data organization and access, dictating the order of elements in our collections.

Quick Recap on Sorting Collections

Sorting collections involves arranging elements in a particular order, making operations like searching within a range more efficient. In Go, while a map doesn't maintain order, sorting can be achieved by extracting keys into a slice and using the sort package:

Go
1package main 2 3import ( 4 "fmt" 5 "sort" 6) 7 8func main() { 9 m := map[string]int{"a": 1, "c": 3, "b": 2} 10 keys := make([]string, 0, len(m)) 11 12 for k := range m { 13 keys = append(keys, k) 14 } 15 16 sort.Strings(keys) 17 18 for _, k := range keys { 19 fmt.Printf("%s=%d\n", k, m[k]) // Outputs "a=1", "b=2", "c=3" 20 } 21}
Introduction to Structs in Go

Structs in Go allow us to create complex data types that encapsulate multiple properties, suitable for representing entities like a Person or a Book. Structs serve as blueprints for creating instances with specific data.

Go
1package main 2 3import "fmt" 4 5type Person struct { 6 Name string 7 Age int 8} 9 10func main() { 11 person := Person{Name: "John Doe", Age: 30} 12 fmt.Println(person.Name) // Outputs "John Doe" 13 fmt.Println(person.Age) // Outputs 30 14}
Using Structs and Slices for Custom Sorting

Using structs along with slices allows us to organize complex data. Consider using structs with slices in lieu of data structures that require sorted keys:

Go
1package main 2 3import ( 4 "fmt" 5 "sort" 6) 7 8type Person struct { 9 Name string 10 Age int 11} 12 13func main() { 14 people := []Person{ 15 {"John", 30}, 16 {"Alice", 25}, 17 } 18 19 sort.Slice(people, func(i, j int) bool { 20 if people[i].Age != people[j].Age { 21 return people[i].Age < people[j].Age 22 } 23 return people[i].Name < people[j].Name 24 }) 25 26 for _, person := range people { 27 fmt.Printf("%s is %d years old\n", person.Name, person.Age) 28 } 29 // Output: 30 // Alice is 25 years old 31 // John is 30 years old 32}

In this example, we create a Person struct and sort a slice of Person using custom criteria defined in a sort.Slice function. We define custom sorting criteria using a lambda function, which allows us to specify the logic for determining the order of the elements. The lambda function is passed as an argument to the sort.Slice function, where it takes two indices, i and j, and returns true if the element at index i should appear before the element at index j. This flexibility lets us sort the Person slice first by Age and then by Name if the ages are equal.

Sorting with sort.Sort, Len, Swap, and Less

In Go, while the sort.Slice function provides straightforward sorting with custom comparator functions, the sort.Sort function offers a more customizable approach. This method requires you to implement the sort.Interface for the collection you want to sort, which involves defining three essential methods: Len(), Swap(), and Less().

Go
1package main 2 3import ( 4 "fmt" 5 "sort" 6) 7 8type Person struct { 9 Name string 10 Age int 11} 12 13type ByAge []Person 14 15func (a ByAge) Len() int { return len(a) } 16func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 17func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age } 18 19func main() { 20 people := []Person{ 21 {"John", 30}, 22 {"Alice", 25}, 23 } 24 25 sort.Sort(ByAge(people)) 26 27 for _, person := range people { 28 fmt.Printf("%s is %d years old\n", person.Name, person.Age) 29 } 30 // Output: 31 // Alice is 25 years old 32 // John is 30 years old 33}

In this example, we define a new type ByAge which is a slice of Person. We then satisfy the sort.Interface by implementing Len(), Swap(), and Less() methods. Len() returns the number of elements, Swap() exchanges elements at given indices, and Less() determines the sorting order, here sorting by Age. By declaring the slice with ByAge and passing it to sort.Sort, we sort the people slice according to the logic in the Less() method. This approach allows fine-grained control over sorting operations using Go's interface mechanism.

Lesson Summary

We've examined how to use slices and the sort package in Go to achieve sorted data similar to sorted dictionaries. By leveraging Go's sorting functions and customizing sorting criteria, we can maintain ordered collections. Structs facilitate the organization of complex data, allowing for efficient manipulation and retrieval based on sorted attributes. Prepare for hands-on exercises to reinforce these concepts.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.