Leveraging an interface, we can implement the sort interface to effectively sort a slice of anything in golang
Take me to the google playground!!!
I didn't see great examples of this while googling, so I thought I'd write a short blog post about it.
First, our structs.
type Veggie struct {
Name string
Foo string
}
type Fruit struct {
Name string
Bar string
}
You'll notice I purposefully made Fruit and Veggie and Foo/Bar attributes so they could not be type converted - no cheating! However, they share an attribute called Name
that we'll eventually sort by.
Next, we're going to define an interface that both Fruit and Veggie implement. (WARNING: my naming conventions are inspired by my rails background so bear with me)
// Nameable is an interface - when implemented - allows the underlying struct to be sorted by the return value
type Nameable interface {
GetName() string
}
// GetName implements the Nameable interface on Veggie
func (v Veggie) GetName() string {
return v.Name
}
// GetName implements the Nameable interface on Fruit
func (f Fruit) GetName() string {
return f.Name
}
Cool, so now both our Fruit and Veggie structs implement the Nameable
interface.
Next, we're going to create a slice type that allows us to create a slice of anything that implements the Nameable
interface.
type Nameables []Nameable
Lastly, we implement the sort interface on our Nameables
type.
func (n Nameables) Len() int {
return len(n)
}
func (n Nameables) Less(i, j int) bool {
return n[i].GetName() < n[j].GetName()
}
func (n Nameables) Swap(i, j int) {
n[i], n[j] = n[j], n[i]
}
Cool, so assuming this is all implemented, what does our code look like?
func main() {
carrot := Veggie{Name: "Carrot", Foo: "Root"}
apple := Fruit{Name: "Apple", Bar: "Seed"}
combined := Nameables{carrot, apple}
sort.Sort(combined)
fmt.Printf("Conversion: %v", combined)
}
And after running this, we should see: Conversion: [{Apple Seed} {Carrot Root}]
You can tell it's neat by the way that it is! How neat is that?