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等类型类似。

Go语言中使用切片(slice)实现一个Vector容器的更多相关文章

  1. Go语言中的切片(十)

    go中数组的长度是固定的,且不同长度的数组是不同类型,这样的限制带来不少局限性.于是切片就来了,切片(Slice)是一个拥有相同类型元素的可变长度的序列.它是基于数组类型做的一层封装.它非常灵活,支持 ...

  2. [Go] gocron源码阅读-go语言中的切片和类型综合

    在gocron.go文件的main函数中,有下面这一句,从这句代码中可以学习到切片和类型的综合运用 cliApp.Flags = append(cliApp.Flags, []cli.Flag{}.. ...

  3. [Go] gocron源码阅读-go语言中的切片接口和类型综合

    // getCommands func getCommands() []cli.Command { command := cli.Command{ Name: "web", Usa ...

  4. Go语言数组和切片的原理

    目录 数组 创建 访问和赋值 切片 结构 初始化 访问 追加 拷贝 总结 数组和切片是 Go 语言中常见的数据结构,很多刚刚使用 Go 的开发者往往会混淆这两个概念,数组作为最常见的集合在编程语言中是 ...

  5. 2.C语言中的关键字

    1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...

  6. go语言的 数组、slice、map使用(转)

    golang群 点击加入 go语言的 数组.slice.map使用, 由于网上有很好的说明, 不需要再写了,请看这几篇: Go语言中的 Array, Slice和 Map 深入学习golang五篇,以 ...

  7. C语言中的结构体,结构体数组

    C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...

  8. python 和 R 语言 中的 range() 函数

    1.python 中的 range() 函数生成整数序列,常用于 for 循环的迭代. 示例: 2.R 语言中的 range() 函数返回一个数值向量中的最小值和最大中,常用于求极差. 示例: 按语: ...

  9. C语言中的关键字总结

    1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...

随机推荐

  1. python字典的增删改查操作

    一.字典  (键值对) 1.字典的基本格式:{key1:1,key2:2} 2.字典里的键必须是不可变的(如:数字,字符串,元组,bool值);值是可变的,可用数字,字符串,列表,字典等. 3.字典里 ...

  2. Js 提交 form 表单

    本文主要讲如何使用Js提交表单,在使用ajax进行异步验证的多数情况下,需要使用Js提交表单,以下简单说几种提交表单的方式: 1.document.getElementById("formI ...

  3. 巧用getdate()测试你的sql执行效率

    在开发项目的过程中,我们会遇到各种各样的问题,有时候由于业务逻辑复杂,我们写的sql语句会很长很长,甚至会嵌套很多层,这个时候我就会担心sql执行时间会不会太长了?会不会有什么问题导致执行效率变慢?经 ...

  4. 8、Docker常用安装:tomcat、mysql、redis

    1.总体步骤 搜索镜像 拉取镜像 查看镜像 启动镜像 停止容器 移除容器 2.安装tomcat 1.docker hub上面查找tomcat镜像 docker search tomcat 2.从doc ...

  5. std::array,std::vector,基于范围的for循环

    std::array除了有传统数组支持随机访问.效率高.存储大小固定等特点外,还支持迭代器访问.获取容量.获得原始指针等高级功能.而且它还不会退化成指针T *给开发人员造成困惑. for( 元素名变量 ...

  6. Guardian of Decency POJ - 2771 【二分匹配,最大独立集】

    Problem DescriptionFrank N. Stein is a very conservative high-school teacher. He wants to take some ...

  7. 001_UCOSIII引入原因

    (一)在前年的学习中一直都是在裸机上跑程序的,根本没有用到操作系统,但是因为以前开发的东西很小,根本用不着,也没必要在操作系统上跑,所以就没有学习.在未来的几天中将进军UCOSIII.为什么选择UCO ...

  8. vue使用Echarts图表

    vue使用Echarts图表 童话_xxv 关注  0.5 2018.12.11 09:09* 字数 325 阅读 1456评论 2喜欢 13 在开发后台系统时,使用图表进行数据可视化,这样会使数据更 ...

  9. CF557E Ann and Half-Palindrome 字典树+dp

    现在看这道题也不难啊,不知道考场上为啥没切~ code: #include <bits/stdc++.h> #define N 5006 #define setIO(s) freopen( ...

  10. 1-4CMYK色彩模式

    http://www.missyuan.com/thread-350717-1-1.html CMYK也称作印刷色彩模式,顾名思义就是用来印刷的. 只要是在印刷品上看到的图像,就是CMYK模式表现的 ...