ronnie
2022-10-14 1504bb53e29d3d46222c0b3ea994fc494b48e153
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
 
package sort_test
 
import (
   "fmt"
   "sort"
)
 
// A couple of type definitions to make the units clear.
type earthMass float64
type au float64
 
// A Planet defines the properties of a solar system object.
type Planet struct {
   name     string
   mass     earthMass
   distance au
}
 
// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(p1, p2 *Planet) bool
 
// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(planets []Planet) {
   ps := &planetSorter{
       planets: planets,
       by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
   }
   sort.Sort(ps)
}
 
// planetSorter joins a By function and a slice of Planets to be sorted.
type planetSorter struct {
   planets []Planet
   by      func(p1, p2 *Planet) bool // Closure used in the Less method.
}
 
// Len is part of sort.Interface.
func (s *planetSorter) Len() int {
   return len(s.planets)
}
 
// Swap is part of sort.Interface.
func (s *planetSorter) Swap(i, j int) {
   s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}
 
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *planetSorter) Less(i, j int) bool {
   return s.by(&s.planets[i], &s.planets[j])
}
 
var planets = []Planet{
   {"Mercury", 0.055, 0.4},
   {"Venus", 0.815, 0.7},
   {"Earth", 1.0, 1.0},
   {"Mars", 0.107, 1.5},
}
 
// ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
func Example_sortKeys() {
   // Closures that order the Planet structure.
   name := func(p1, p2 *Planet) bool {
       return p1.name < p2.name
   }
   mass := func(p1, p2 *Planet) bool {
       return p1.mass < p2.mass
   }
   distance := func(p1, p2 *Planet) bool {
       return p1.distance < p2.distance
   }
   decreasingDistance := func(p1, p2 *Planet) bool {
       return distance(p2, p1)
   }
 
   // Sort the planets by the various criteria.
   By(name).Sort(planets)
   fmt.Println("By name:", planets)
 
   By(mass).Sort(planets)
   fmt.Println("By mass:", planets)
 
   By(distance).Sort(planets)
   fmt.Println("By distance:", planets)
 
   By(decreasingDistance).Sort(planets)
   fmt.Println("By decreasing distance:", planets)
 
   // Output: By name: [{Earth 1 1} {Mars 0.107 1.5} {Mercury 0.055 0.4} {Venus 0.815 0.7}]
   // By mass: [{Mercury 0.055 0.4} {Mars 0.107 1.5} {Venus 0.815 0.7} {Earth 1 1}]
   // By distance: [{Mercury 0.055 0.4} {Venus 0.815 0.7} {Earth 1 1} {Mars 0.107 1.5}]
   // By decreasing distance: [{Mars 0.107 1.5} {Earth 1 1} {Venus 0.815 0.7} {Mercury 0.055 0.4}]
}