I have set of json data being pulled from a rethink database, the data is then serialised into structs using rethinkgo. I need to be able to work with a subset of this data and sort it based on the value of one of its properties.
To save complicating the problem with the workings of what I mentioned above, I've created a simplified (fruit based) example of the structs being used and what I'm trying to achieve.
package main
import (
"fmt"
"sort"
)
type Fruit struct {
AvgNumSeeds int
Name string
}
type Apple struct {
Fruit
Diameter int
}
type Banana struct {
Fruit
Length int
}
type ByNumSeeds []Apple //[]Fruit
func (p ByNumSeeds) Len() int {
return len(p)
}
func (p ByNumSeeds) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func (p ByNumSeeds) Less(i, j int) bool {
return p[i].AvgNumSeeds < p[j].AvgNumSeeds
}
func main() {
apples := []Apple{
Apple{Fruit: Fruit{AvgNumSeeds: 4, Name: "Cox"}, Diameter: 10},
Apple{Fruit: Fruit{AvgNumSeeds: 6, Name: "Granny Smith"}, Diameter: 20},
Apple{Fruit: Fruit{AvgNumSeeds: 5, Name: "Pink Lady"}, Diameter: 21},
Apple{Fruit: Fruit{AvgNumSeeds: 2, Name: "Russett"}, Diameter: 15},
Apple{Fruit: Fruit{AvgNumSeeds: 1, Name: "Crab"}, Diameter: 7},
Apple{Fruit: Fruit{AvgNumSeeds: 7, Name: "Brambley"}, Diameter: 40},
Apple{Fruit: Fruit{AvgNumSeeds: 3, Name: "Braeburn"}, Diameter: 25},
}
bananas := []Banana{
Banana{Fruit: Fruit{AvgNumSeeds: 40, Name: "Lacatan"}, Length: 20},
Banana{Fruit: Fruit{AvgNumSeeds: 60, Name: "Lady Finger"}, Length: 22},
Banana{Fruit: Fruit{AvgNumSeeds: 50, Name: "Senorita"}, Length: 25},
Banana{Fruit: Fruit{AvgNumSeeds: 20, Name: "Cavendish"}, Length: 30},
Banana{Fruit: Fruit{AvgNumSeeds: 10, Name: "Goldfinger"}, Length: 27},
Banana{Fruit: Fruit{AvgNumSeeds: 70, Name: "Gros Michel"}, Length: 15},
Banana{Fruit: Fruit{AvgNumSeeds: 30, Name: "Red Dacca"}, Length: 19},
}
fmt.Println("Apples")
fmt.Printf("%+v
", apples)
sort.Sort(ByNumSeeds(apples))
fmt.Printf("%+v
", apples)
fmt.Println("Bananas")
fmt.Printf("%+v
", bananas)
//sort.Sort(ByNumSeeds(bananas))
fmt.Printf("%+v
", bananas)
}
http://play.golang.org/p/EjWOf58N3x
As you can see I've two structs, Apples and Bananas, both of which share properties from the struct Fruit; a sort (inc. interface functions Len, Swap, Less) and the main function which sets up the data structures for apples and bananas and then tries to sort them.
What I am wanting for both Apples and Bananas is one sort (type ByNumSeeds, Len, Swap, Less) that is capable of sorting both Apples and Bananas separately, on a property that they both share from the Fruit struct, AvgNumSeeds.
The sort I have created in this code takes a slice of Apples as its interface and does indeed sort my array of apples by the AvgNumSeeds. However I am unable to find a way to get it to work with both Apple and Banana structs.
My initial thought was to treat the interface as a slice of Fruit but, understandably, I then get the error:
60: cannot convert apples (type []Apple) to type ByNumSeeds
My next thought was to fix this error by somehow casting a slice of Apples/Bananas to a slice of Fruit but this doesn't quite feel like the right thing to do.
In my investigation for a solution I've come across a package called sortutil which has a function called AscByField that takes the struct and the name of the field to sort by. I've not tried it yet but the package makes it quite clear that its not efficient as it works by using reflection and to try to use the standard interface method first.
Is there a way I can achieve the sorting of a nested struct without having to duplicate a sort for each 'child' struct type?