|  | // 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}] | 
|  | } |