开始文章之前我们要先弄清楚什么是『泛型编程』。
简单来说就说,我们编写的代码不是针对特定的类型(比如适用于int, 不适用于string)才有效,而是大部分类型的参数都是可以工作的。
我们来看一个C++的例子:
int main() { std::vector A{3,1,2,4,5}; std::vector B{"golang", "I", "am"}; std::sort(A.begin(), A.end());//after this, A={1,2,3,4,5} std::sort(B.begin(), B.end());//after this, B={"I", "am", "golang"} return 0;}
这里的sort函数就是一个泛型编程例子。至于为什么{“golang”, “I”, “am”}排序之后变成{“I”, “am”, “golang”}是因为string类型的比较函数是字典序。细心的人可能会注意到这儿直接使用大括号来初始化vector,是的,这是C++11。
Go有泛型编程吗?没有。
为什么Go没有泛型编程?
尽管泛型很好,但是它会让我们的语言设计复杂度提升,所以我们现在暂时不打算支持,以后可能会支持。另外,虽然我们现在很弱,但是使用Interface也是可以实现泛型了(呵呵)。
Go的泛型编程实现
前面说了使用Go的interface可以实现泛型编程,那么我们先理解一下interface。
这里引入一个概念,duck typing。结合维基百科的定义,duck typing是面向对象编程语言的一种类型定义方法。我们判断一个对象是神马不是通过它的类型定义来判断,而是判断它是否满足某些特定的方法和属性定义。
interface 那么Go中interface是什么呢?interface是一组方法集合。我们可以把它看成一种定义内部方法的动态数据类型,任意实现了这些方法的数据类型都可以认为是特定的数据类型。
泛型编程 其实Go语言中也提供了sort函数,我们看一下源码,src/sort/sort.go。
package sort// A type, typically a collection, that satisfies sort.Interface can be// sorted by the routines in this package. The methods require that the// elements of the collection be enumerated by an integer index.type Interface interface { // Len is the number of elements in the collection. Len() int // Less reports whether the element with // index i should sort before the element with index j. Less(i, j int) bool // Swap swaps the elements with indexes i and j. Swap(i, j int)}...// Sort sorts data.// It makes one call to data.Len to determine n, and O(n*log(n)) calls to// data.Less and data.Swap. The sort is not guaranteed to be stable.func Sort(data Interface) { // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached. n := data.Len() maxDepth := 0 for i := n; i > 0; i >>= 1 { maxDepth++ } maxDepth *= 2 quickSort(data, 0, n, maxDepth)}
其中省略了一些源码,我们看到package中定义了一个Interface,包含三个方法:Len(), Less(), Swap()。Interface作为参数传递给Sort。我们要使用Sort,只需要实现Interface的三个方法就可以使用下面是一个例子。
package mainimport ( "fmt" "sort")type Person struct { Name string Age int}func (p Person) String() string { return fmt.Sprintf("%s: %d", p.Name, p.Age)}// ByAge implements sort.Interface for []Person based on// the Age field.type ByAge []Personfunc (a ByAge) Len() int { return len(a) }func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }func main() { people := []Person{ {"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}, } fmt.Println(people) sort.Sort(ByAge(people)) fmt.Println(people)}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iM5UDO1ImNkRmZ1UTO0YTMkBzMkBjY4YjY3kzY1AjYm9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)