Golang 中"泛型"的支持

Golang不支持一般的類似java中的標記式泛型。很多人因此而十分不滿,認爲沒有泛型增加了很多工作量。而目前由於泛型支持的複雜性,Golang的設計和實現者並沒有把這個泛型支持作爲緊急需要增加的特性。但是,如果真的沒有泛型,就一定不行了麼?答案當然是否定的。沒有泛型也可以,而且我覺得代碼更簡單,直接,有趣(個人觀點,勿噴)。

我們這裏打算以一些例子來講解Golang中如何處理這個問題。

首先,我們看一個冒泡排序的問題。針對整型數組切片的排序。

package main

import (
	"fmt"
)

func bubbleSort(array []int) {
	for i := 0; i < len(array); i++ {
		for j := 0; j < len(array)-i-1; j++ {
			if array[j] > array[j+1] {
				array[j], array[j+1] = array[j+1], array[j]
			}
		}
	}
}

func main() {
	a1 := []int{3, 2, 6, 10, 7, 4, 6, 5}
	bubbleSort(a1)
	fmt.Println(a1)
}

上面的例子輸出爲:

[2 3 4 5 6 6 7 10]

那麼,我們如果希望這個bubbleSort能夠同時支持float類型數據排序,或者是按照字符串的長度來排序應該怎麼做呢?在其他的例如java語言中,我們可以將bubbleSort定義爲支持泛型的排序,但是Go裏面就不行了。爲了達到這個目的,我們可以使用interface來實現相同的功能。

針對上面的排序問題,我們可以分析一下排序的步驟:

  1. 查看切片長度,以用來遍歷元素(Len);
  2. 比較切片中的兩個元素(Less);
  3. 根據比較的結果決定是否交換元素位置(Swap)。
    到這裏,或許你已經明白了,我們可以把上面的函數分解爲一個支持任意類型的接口,任何其他類型的數據只要實現了這個接口,就可以用這個接口中的函數來排序了。
type Sortable interface{
	Len() int
	Less(int, int) bool
	Swap(int, int)
}

下面,我們就用幾個例子來描述一下這個接口的用法。

package main

import (
	"fmt"
)

type Sortable interface {
	Len() int
	Less(int, int) bool
	Swap(int, int)
}

func bubbleSort(array Sortable) {
	for i := 0; i < array.Len(); i++ {
		for j := 0; j < array.Len()-i-1; j++ {
			if array.Less(j+1, j) {
				array.Swap(j, j+1)
			}
		}
	}
}

//實現接口的整型切片
type IntArr []int

func (array IntArr) Len() int {
	return len(array)
}

func (array IntArr) Less(i int, j int) bool {
	return array[i] < array[j]
}

func (array IntArr) Swap(i int, j int) {
	array[i], array[j] = array[j], array[i]
}

//實現接口的字符串,按照長度排序
type StringArr []string

func (array StringArr) Len() int {
	return len(array)
}

func (array StringArr) Less(i int, j int) bool {
	return len(array[i]) < len(array[j])
}

func (array StringArr) Swap(i int, j int) {
	array[i], array[j] = array[j], array[i]
}

//測試
func main() {
	intArray1 := IntArr{3, 4, 2, 6, 10, 1}
	bubbleSort(intArray1)
	fmt.Println(intArray1)

	stringArray1 := StringArr{"hello", "i", "am", "go", "lang"}
	bubbleSort(stringArray1)
	fmt.Println(stringArray1)
}

輸出結果爲:

[1 2 3 4 6 10]
[i am go lang hello]

上面的例子中,我們首先定義了一個IntArr類型的整型切片類型,然後讓這個類型實現了Sortable接口,然後在測試代碼中,這個IntArr類型就可以直接調用Sortable接口的bubbleSort方法了。

另外,我們還演示了一個字符串切片類型StringArr按照字符串長度來排序的例子。和IntArr類型一樣,它實現了Sortable即可定義的方法,然後就可以用Sortable即可的bubbleSort方法來排序了。

總結
上面的例子,是一種Golang中支持所謂的“泛型”的方法。這種泛型當然不是真正意義上面的泛型,但是提供了一種針對多種類型的一致性方法的參考實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章