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等类型类似。
Go语言中使用切片(slice)实现一个Vector容器的更多相关文章
- Go语言中的切片(十)
go中数组的长度是固定的,且不同长度的数组是不同类型,这样的限制带来不少局限性.于是切片就来了,切片(Slice)是一个拥有相同类型元素的可变长度的序列.它是基于数组类型做的一层封装.它非常灵活,支持 ...
- [Go] gocron源码阅读-go语言中的切片和类型综合
在gocron.go文件的main函数中,有下面这一句,从这句代码中可以学习到切片和类型的综合运用 cliApp.Flags = append(cliApp.Flags, []cli.Flag{}.. ...
- [Go] gocron源码阅读-go语言中的切片接口和类型综合
// getCommands func getCommands() []cli.Command { command := cli.Command{ Name: "web", Usa ...
- Go语言数组和切片的原理
目录 数组 创建 访问和赋值 切片 结构 初始化 访问 追加 拷贝 总结 数组和切片是 Go 语言中常见的数据结构,很多刚刚使用 Go 的开发者往往会混淆这两个概念,数组作为最常见的集合在编程语言中是 ...
- 2.C语言中的关键字
1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...
- go语言的 数组、slice、map使用(转)
golang群 点击加入 go语言的 数组.slice.map使用, 由于网上有很好的说明, 不需要再写了,请看这几篇: Go语言中的 Array, Slice和 Map 深入学习golang五篇,以 ...
- C语言中的结构体,结构体数组
C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...
- python 和 R 语言 中的 range() 函数
1.python 中的 range() 函数生成整数序列,常用于 for 循环的迭代. 示例: 2.R 语言中的 range() 函数返回一个数值向量中的最小值和最大中,常用于求极差. 示例: 按语: ...
- C语言中的关键字总结
1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...
随机推荐
- python字典的增删改查操作
一.字典 (键值对) 1.字典的基本格式:{key1:1,key2:2} 2.字典里的键必须是不可变的(如:数字,字符串,元组,bool值);值是可变的,可用数字,字符串,列表,字典等. 3.字典里 ...
- Js 提交 form 表单
本文主要讲如何使用Js提交表单,在使用ajax进行异步验证的多数情况下,需要使用Js提交表单,以下简单说几种提交表单的方式: 1.document.getElementById("formI ...
- 巧用getdate()测试你的sql执行效率
在开发项目的过程中,我们会遇到各种各样的问题,有时候由于业务逻辑复杂,我们写的sql语句会很长很长,甚至会嵌套很多层,这个时候我就会担心sql执行时间会不会太长了?会不会有什么问题导致执行效率变慢?经 ...
- 8、Docker常用安装:tomcat、mysql、redis
1.总体步骤 搜索镜像 拉取镜像 查看镜像 启动镜像 停止容器 移除容器 2.安装tomcat 1.docker hub上面查找tomcat镜像 docker search tomcat 2.从doc ...
- std::array,std::vector,基于范围的for循环
std::array除了有传统数组支持随机访问.效率高.存储大小固定等特点外,还支持迭代器访问.获取容量.获得原始指针等高级功能.而且它还不会退化成指针T *给开发人员造成困惑. for( 元素名变量 ...
- Guardian of Decency POJ - 2771 【二分匹配,最大独立集】
Problem DescriptionFrank N. Stein is a very conservative high-school teacher. He wants to take some ...
- 001_UCOSIII引入原因
(一)在前年的学习中一直都是在裸机上跑程序的,根本没有用到操作系统,但是因为以前开发的东西很小,根本用不着,也没必要在操作系统上跑,所以就没有学习.在未来的几天中将进军UCOSIII.为什么选择UCO ...
- vue使用Echarts图表
vue使用Echarts图表 童话_xxv 关注 0.5 2018.12.11 09:09* 字数 325 阅读 1456评论 2喜欢 13 在开发后台系统时,使用图表进行数据可视化,这样会使数据更 ...
- CF557E Ann and Half-Palindrome 字典树+dp
现在看这道题也不难啊,不知道考场上为啥没切~ code: #include <bits/stdc++.h> #define N 5006 #define setIO(s) freopen( ...
- 1-4CMYK色彩模式
http://www.missyuan.com/thread-350717-1-1.html CMYK也称作印刷色彩模式,顾名思义就是用来印刷的. 只要是在印刷品上看到的图像,就是CMYK模式表现的 ...