目前Golang最新版本为1.9, 暂时不支持泛型。
不过可以通过interface实现”泛型编程”效果, 下面以slice类型数据的添加/删除元素为例,
供大家参考一下:
package main
import (
"errors"
"fmt"
)
var (
ERR_ELEM_EXISTS = errors.New("element exits.")
ERR_ELEM_NOT_EXISTS = errors.New("element not exits.")
)
// 定义切片,支持interface{}类型
// 假设该slice不支持存储相同元素
type SomeSlice []interface{}
// 初始化slice实例
func NewSomeSlice() SomeSlice {
return make(SomeSlice, 0)
}
// 定义一个用于对比的接口
type Comparable interface {
IsEqual(a interface{}) bool
}
// 定义struct类型
type Employee struct {
Id int32
Name string
}
// Employee类型实现了Comparable接口
func (em Employee) IsEqual(b interface{}) bool {
if em2, ok := b.(Employee); ok {
return em.Id == em2.Id
} else {
return false
}
}
// isEqual函数用于各种类型之间的比较
func isEqual(a, b interface{}) bool {
if cmpa, ok := a.(Comparable); ok {
return cmpa.IsEqual(b)
} else if cmpb, ok := b.(Comparable); ok {
return cmpb.IsEqual(a)
} else {
return a == b
}
}
// 向slice添加元素
func (ss *SomeSlice) Add(elem interface{}) error {
for _, v := range *ss {
if isEqual(v, elem) {
fmt.Printf("[Error]Cannot add the same element: %v\n", elem)
return ERR_ELEM_EXISTS
}
}
*ss = append(*ss, elem)
return nil
}
//从slice中删除元素
func (ss *SomeSlice) Remove(elem interface{}) error {
for k, v := range *ss {
if isEqual(v, elem) {
if k == len(*ss)-1 {
*ss = (*ss)[:k]
} else {
*ss = append((*ss)[:k], (*ss)[k+1:]...)
}
return nil
}
}
fmt.Printf("[Error]No such element: %v\n", elem)
return ERR_ELEM_NOT_EXISTS
}
func main() {
// 初始化slice
slice := NewSomeSlice()
// 正常情况下添加不同类型元素
slice.Add(5)
slice.Add("huahua")
slice.Add(Employee{Id: 123, Name: "xiaohong"})
slice.Add(10)
slice.Add("xiaoming")
slice.Add(Employee{Id: 456, Name: "xiaogang"})
fmt.Println("After Add, Current Slice:", slice)
// 添加了重复的元素
slice.Add(10)
slice.Add("huahua")
slice.Add(Employee{Id: 456, Name: "xiaogang"})
fmt.Println("After invalid Add, Current Slice:", slice)
// 正常情况下删除元素
slice.Remove(5)
slice.Remove("huahua")
slice.Remove(Employee{Id: 456, Name: "xiaogang"})
fmt.Println("After Remove, Current Slice:", slice)
// 删除并不存在的元素
slice.Remove(11)
slice.Remove("somename")
slice.Remove(Employee{Id: 789, Name: "dajiu"})
fmt.Println("After invalid Remove, Current Slice:", slice)
}
运行结果如下所示:
pintai@MG:~/src$ go run tmpl.go
After Add, Current Slice: [5 huahua {123 xiaohong} 10 xiaoming {456 xiaogang}]
[Error]Cannot add the same element: 10
[Error]Cannot add the same element: huahua
[Error]Cannot add the same element: {456 xiaogang}
After invalid Add, Current Slice: [5 huahua {123 xiaohong} 10 xiaoming {456 xiaogang}]
After Remove, Current Slice: [{123 xiaohong} 10 xiaoming]
[Error]No such element: 11
[Error]No such element: somename
[Error]No such element: {789 dajiu}
After invalid Remove, Current Slice: [{123 xiaohong} 10 xiaoming]
上面的例子实现了支持不同类型元素的slice,通过Add/Remove方法进行增删元素。
其中一个关键方法是isEqual, 对于实现了Comparable类型的对象使用了它的IsEqual方法来比较,对于其他类型(基础类型)数据则直接用 == 来进行比较。