Go的组合在sort包中的应用

108 阅读1分钟

背景

今天有小伙伴问Go里面如何给自定义类型排序,然后我让她实现了一下sort包里面的几个方法,当然就是Len(),Less()和Swap()了,常规操作,不过她额外在代码里面加了一个逆序排序的操作,我CodeReview的时候看了一把,顿时有些疑惑。代码大概类似下面这个:

package main

import (
	"sort"
	"fmt"
)

func main() {
	var s = []int{4, 3, 6, 7, 3, 1}
	sort.Sort(sort.Reverse(sort.IntSlice(s)))
	fmt.Println(s)
}

本来我觉得至少得这么写,先排序,再逆序一把,就像这样(实际不行):

sort.Sort(sort.IntSlice(s))
sort.Reverse(sort.IntSlice(s))

解惑

出于好奇,我翻了下Go的源码,发现了端倪:

type reverse struct {
	// This embedded Interface permits Reverse to use the methods of
	// another Interface implementation.
	Interface
}

// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
	return r.Interface.Less(j, i)
}

// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
	return &reverse{data}
}

这个 Reverse 方法没那么简单,它是在传入的参数之上有封装了一个 reverse 类型,这个类型通过组合的方式继承了传入参数的排序接口实现,但是在这里它覆盖了原传入参数类型的Less()方法,而实际上再交给 sort.Sort() 函数进行排序的类型已经是新的 reverse 类型了,十分有意思的技巧,代码虽少,但是阐述了Go里面组合类型的使用方法。