Go语言中使用切片(slice)实现一个Vector容器
Go语言中的切片(slice)和一些内置函数能实现其他语言容器类Array、Vector的功能,但是Go内置语言包container里只提供了list、heap、ring三种容器,缺少vector容器,在实际的项目中为使用方便有必要包装一个vector,提供vector的常见功能。
C++、Java、C#等语言支持泛型,Go语言不支持泛型,可以用 interface{} 提供类似泛型的支持。下面是vector容器代码
package vector import ( "reflect" ) // 小写 只能通过工厂函数创建 type vector struct { values []interface{} } // 创建工厂函数 func New(cap int) *vector { this := new(vector) this.values = make([]interface{}, 0, cap) return this } func (this *vector) IsEmpty() bool { return len(this.values) == 0 } // 元素数量 func (this *vector) Size() int { return len(this.values) } // 追加单个元素 func (this *vector) Append(value interface{}) bool { this.values = append(this.values, value) return true } // 追加元素切片 func (this *vector) AppendAll(values []interface{}) bool { if values == nil || len(values) < 1 { return false } this.values = append(this.values, values...) return true } // 插入单个元素 func (this *vector) Insert(index int, value interface{}) bool { if index < 0 || index >= len(this.values) { return false } this.values = append(this.values[:index], append([]interface{}{value}, this.values[index:]...)...) return true } // 插入元素切片 func (this *vector) InsertAll(index int, values []interface{}) bool { if index < 0 || index >= len(this.values) || values == nil || len(values) < 1 { return false } this.values = append(this.values[:index], append(values, this.values[index:]...)...) return true } // 移除 func (this *vector) Remove(index int) bool { if index < 0 || index >= len(this.values) { return false } // 重置为 nil 防止内存泄漏 this.values[index] = nil this.values = append(this.values[:index], this.values[index+1:]...) return true } // 范围移除 从 fromIndex(包含) 到 toIndex(不包含) 之间的元素 func (this *vector) RemoveRange(fromIndex, toIndex int) bool { if fromIndex < 0 || fromIndex >= len(this.values) || toIndex > len(this.values) || fromIndex > toIndex { return false } // 重置为 nil 防止内存泄漏 for i := fromIndex; i < toIndex; i++ { this.values[i] = nil } this.values = append(this.values[:fromIndex], this.values[toIndex:]...) return true } // 全部移除 func (this *vector) RemoveAll() { // 重置为 nil 防止内存泄漏 for i := 0; i < this.Size(); i++ { this.values[i] = nil } this.values = this.values[0:0] } func (this *vector) getIndex(value interface{}) int { for i := 0; i < len(this.values); i++ { if reflect.DeepEqual(this.values[i], value) { return i } } return -1 } // 是否存在该元素值 func (this *vector) Contains(value interface{}) bool { return this.getIndex(value) >= 0 } // 获取元素值第一次出现的索引 func (this *vector) IndexOf(value interface{}) int { return this.getIndex(value) } // 获取元素值最后一次出现的索引 func (this *vector) LastIndexOf(value interface{}) int { for i := len(this.values) - 1; i >= 0; i-- { if reflect.DeepEqual(this.values[i], value) { return i } } return -1 } // 得到索引对应的元素值 func (this *vector) GetValue(index int) interface{} { if index < 0 || index >= len(this.values) { return nil } return this.values[index] } // 设置值 func (this *vector) SetValue(index int, value interface{}) bool { if index < 0 || index >= len(this.values) { return false } this.values[index] = value return true } func (this *vector) ToArray() []interface{} { dst := make([]interface{}, this.Size()) copy(dst, this.values) return dst }
vector内部使用切片(slice)保存元素值,元素类型 interface{},泛型。getIndex()方法使用reflect.DeepEqual()函数对元素值作深度比较。上述代码只提供了vector容器常见功能,更多的功能可以根据需要添加,比如有的时候需要对容器中的元素排序,则可以添加排序方法。
一些方法简单返回bool值表示成功或失败,可以根据需要增加一个error返回值指明失败的详细原因。
需要注意的事项是Remove、RemoveRange、RemoveAll方法内把元素移走时避免内存泄露。
下面是测试代码
func testVector() { v := vector.New(5) for i := 0; i < 6; i++ { v.Append(i) } fmt.Println(*v) fmt.Println(v.IsEmpty()) v.Insert(1, 10) v.Insert(20, 20) fmt.Println(*v) v.Remove(-1) v.Remove(1) v.Remove(100) fmt.Println(*v) fmt.Println(v.IndexOf(3)) fmt.Println(v.IndexOf(300)) fmt.Println(v.GetValue(1)) fmt.Println(v.GetValue(100)) v.SetValue(-1, -1) v.SetValue(1, 11) v.SetValue(100, 101) fmt.Println(*v) v.RemoveAll() fmt.Println(v.IsEmpty()) fmt.Println(v.Size()) v.Append(22) fmt.Println(*v) }
测试代码覆盖了部分可能的情况,创建函数New的cap参数指明容器的初始容量。
上述测试代码只写了int类型的元素,其他string、float、array、map、struct、slice、vector等类型类似。