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. MFC消息路由

    1.Command Routing(命令传递):当消息进来时,会有一个泵推动它前进.消息如何进来,以有泵函数如何推动,都是属于windows程序设计的范畴, 消息如果是从子类流向父类(纵向流动),那么 ...

  2. Java8-LongAccumulator

    import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util ...

  3. asp.net用sql数据库生成json字符串并显示出来

    use Shop ,) )) insert into DictBase select '包装' UNION ALL select '价格' UNION ALL select '品牌' 工厂方法模式 I ...

  4. 5、Spring Boot 2.x 启动原理解析

    1.5 Spring Boot 启动原理解析 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏 ...

  5. Github:VS使用GitHub要点

    1.VS打开[扩展或更新]安装插件[Github Extension for VisualStudio] 2.在团队资源管理中可以Clone线上已经有的库到本地,或者可以新建库同步到线上 3.同步设置 ...

  6. C++指针图解

  7. 使用 ALinq 实现 Linq to MySQL【转】

    http://www.cnblogs.com/huangcong/archive/2011/05/24/2055204.html

  8. IDEA工具的安装、破解与配置

    一.什么是IDEA? IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境,是目前最好用的java集成开发工具.他最突出的功能是调试(Debug),可以对Java代码,Java ...

  9. P4781 拉格朗日插值

    #include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #def ...

  10. vue 图片上传

    功能说明: 1.调用手机拍照功能 2.调用相册功能 3.图片上传功能 4.图片预览功能 5.图片删除功能 关键点: .input 新增multiple .accept="image/*处理I ...