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來實現相同的功能。
針對上面的排序問題,我們可以分析一下排序的步驟:
- 查看切片長度,以用來遍歷元素(Len);
- 比較切片中的兩個元素(Less);
- 根據比較的結果決定是否交換元素位置(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中支持所謂的“泛型”的方法。這種泛型當然不是真正意義上面的泛型,但是提供了一種針對多種類型的一致性方法的參考實現。