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 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...
随机推荐
- redis安装,以及开机自动启动
tcl安装 # wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz# tar -xzvf tcl8.6.1-src.tar.gz ...
- a标签中的javascript:void(0)和#的区别
#包含了一个位置信息 默认的锚是#top 也就是网页的上端 而javascript:void(0) 仅仅表示一个死链接 void(0)用于执行某些处理,但是不整体刷新页面 javascript:v ...
- Python中的memoryview
Python中的memoryview提供了类似C语言指针的功能,有了memoryview,如果某个Object支持buffer protocol,那么就可以通过memory去访问到他的内部. Pyth ...
- 2018 南京网络预赛Sum - 线性筛
题意 链接 定义 $f(x)$ 为满足以下条件的有序二元组 $(a, b)$ 的方案数(即 $(a, b)$ 与 $(b, a)$ 被认为是不同的方案): $x= ab$ $a$ 和 $b$ 均无平方 ...
- 快捷键IntelliJ IDEA For Mac
http://www.cnblogs.com/wxd0108/p/5295017.html Mac键盘符号和修饰键说明 ⌘ Command ⇧ Shift ⌥ Option ⌃ Control ↩︎ ...
- Codeforces Round #551 (Div. 2) E. Serval and Snake (交互题)
人生第一次交互题ac! 其实比较水 容易发现如果查询的矩阵里面包含一个端点,得到的值是奇数:否则是偶数. 所以只要花2*n次查询每一行和每一列,找出其中查询答案为奇数的行和列,就表示这一行有一个端点. ...
- Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 1) 963B 964D B Destruction of a Tree
题 OvO http://codeforces.com/contest/963/problem/B CF 963B 964D 解 对于题目要求,显然一开始的树,要求度数为偶数的节点个数为奇数个,通过奇 ...
- pycharm 头模板
#!/usr/local/bin/python3 # -*- coding: utf-8 -*- """ @author: Ray @contact: raylively ...
- Codeforces Round #553 (Div. 2) 【C. Problem for Nazar】
题目大意: 一开始第一行是 1,第二行是2 4 ,第三行是3 5 7 9 ,类似这样下去,每一行的个数是上一行的个数,然后对这些点从第一个进行编号,问你从[l,r]区间数的和. 思路:分别求出奇数和偶 ...
- [Luogu] 校园网Network of Schools
https://www.luogu.org/problemnew/show/2746 Tarjan 缩点 判断入度为0的点的个数与出度为0的点的个数的关系 注意全缩为一个点的情况 #include & ...