Golang 切片(Slice)实现增删改查


Posted in Golang onApril 22, 2022

引言

Golang 的数组是固定长度,可以容纳相同数据类型的元素的集合。

但是当长度固定了,在使用的时候肯定是会带来一些限制,比如说:申请的长度太大会浪费内存,太小又不够用。

鉴于上述原因,我们有了 go 语言的切片,可以把切片理解为,可变长度的数组,其实它底层就是使用数组实现的,增加了自动扩容功能。

切片(Slice)是一个拥有相同类型元素的可变长度的序列。

一、切片的基础语法

1. 语法

声明一个切片和声明一个数组类似,只要不添加长度即可

var identifier []type

切片是引用类型,可以使用make函数来创建切片:

var slice1 []type =make([]type, len)

也可以简写为

slice1 := make([]type, len)

也可以指定容量,其中capacity为可选参数

make([]T,length,capacity)

这里len是数组的长度并且也是切片的初始长度

2. 示例

切片在没有赋值之前是空值

声明变量的方式创建切片

package main
 
import "fmt"
 
func main() {
    var names []string
    var numbers []int
    fmt.Printf("names: %v\n", names)
    fmt.Printf("numbers: %v\n", numbers)
    fmt.Println(names == nil)
    fmt.Println(numbers == nil)
}

输出结果如下

names: []
numbers: []
true
true

使用make函数创建切片

package main
 
import "fmt"
 
func main() {
    var a = make([]int, 2)
    var b = make([]int, 3)
 
    fmt.Printf("a: %v\n", a)
    fmt.Printf("b: %v\n", b)
}

输出结果如下

a: [0 0]
b: [0 0 0]

3. 切片的长度和容量

切片拥有自己的长度和容量,我们可以通过使用内置的len()函数求出长度,使用内置的cap()函数求出切片的内容。

package main
 
import "fmt"
 
func main() {
    var names = []string{"hello", "world"}
    var num = []int{1, 2, 3}
    fmt.Printf("len: %d cap: %d\n", len(names), cap(names))
    fmt.Printf("len: %d cap: %d\n", len(num), cap(num))
    fmt.Printf("num[2]: %v\n", num[2])//根据下标索引来获取切片的元素
    fmt.Println("-----------")
    var a = make([]string, 2, 3)
    fmt.Printf("len: %d cap: %d", len(a), cap(a))
}

输出结果如下

len: 2 cap: 2
len: 3 cap: 3
num[2]: 3
-----------
len: 2 cap: 3

二、切片的初始化

切片的初始化方式有很多种,可以直接初始化,也可以使用数组初始化。

1. 直接初始化

package main
 
import "fmt"
 
func main() {
    a := []int{1, 2, 3}
    fmt.Printf("a: %v\n", a)
}

输出结果如下

a: [1 2 3]

2. 使用数组初始化

package main
 
import "fmt"
 
func main() {
    a := [...]int{1, 2, 3}
    b := a[:]
    fmt.Printf("b: %v\n", b)
}

输出结果

b: [1 2 3]

3. 使用数组的部分元素初始化(切片表达式)

切片的底层就是一个数组,所以我们可以基于数组通过切片表达式得到切片。

切片表达式中的low和high表示一个索引范围(包左不包右),得到切片的长度=high-low,容量等于得到的切片的底层数组的容量。

package main
 
import "fmt"
 
func main() {
    a := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
    b := a[2:5] //下标2到5,左闭右开,不包括5
    fmt.Printf("b: %v\n", b)
    c := a[2:] //下标2后面的所有
    fmt.Printf("c: %v\n", c)
    d := a[:3] //下标3之前的,不包括3
    fmt.Printf("d: %v\n", d)
    e := a[:] //取所有值
    fmt.Printf("e: %v\n", e)
}

输出结果如下

b: [3 4 5]
c: [3 4 5 6 7 8]
d: [1 2 3]
e: [1 2 3 4 5 6 7 8]

4. 空(nil)切片

一个切片在未初始化之前默认为nil,长度为0,容量为0

package main
 
import "fmt"
 
func main() {
    var a []int
    fmt.Println(a == nil)
    fmt.Printf("len: %d,cap: %d\n", len(a), cap(a))
}

输出结果如下

true
len: 0,cap: 0

三、切片的遍历

切片的遍历和数组的遍历非常类型,可以使用for循环索引遍历,或者for range循环

1. for 循环遍历

package main
 
import "fmt"
 
func main() {
    s1 := []int{1, 2, 3, 4, 5, 6}
    for i := 0; i < len(s1); i++ {
        fmt.Printf("s1[%d]: %v\n", i, s1[i])
    }
}

输出结果如下

s1[0]: 1
s1[1]: 2
s1[2]: 3
s1[3]: 4
s1[4]: 5
s1[5]: 6

2. for range遍历

package main
 
import "fmt"
 
func main() {
    s1 := []int{1, 2, 3, 4, 5, 6}
    for i, v := range s1 {
        fmt.Printf("i: %v,v: %v\n", i, v)
    }
}

输出结果如下,i是索引,v是值

i: 0,v: 1
i: 1,v: 2
i: 2,v: 3
i: 3,v: 4
i: 4,v: 5
i: 5,v: 6

四、切片元素的添加和删除copy

切片是一个动态数组,可以使用append()函数添加元素

go 语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。

由于切片是引用类型,通过赋值的方式,会修改原有内容,go 提供了copy()函数来拷贝切片

1. 添加元素

package main
 
import "fmt"
 
func main() {
    a := []int{}
    a = append(a, 1)
    a = append(a, 2)
    a = append(a, 3, 4, 5) //添加多个元素
    fmt.Printf("a: %v\n", a)
    fmt.Println("---------------------")
    a1 := []int{3, 4, 5}
    a2 := []int{1, 2}
    a2 = append(a2, a1...) //添加另外一个切片进去
    fmt.Printf("a2: %v\n", a2)
}

输出结果如下

a: [1 2 3 4 5]
---------------------
a2: [1 2 3 4 5]

2. 删除元素

Golang 切片(Slice)实现增删改查

package main
 
import "fmt"
 
func main() {
    var s1 = []int{1, 2, 3, 4}
    fmt.Println("---删除之前---")
    fmt.Printf("s1: %v\n", s1)
 
    //删除3这个元素,它的下标索引为2
    s1 = append(s1[:2], s1[3:]...)
    fmt.Println("---删除之后---")
    fmt.Printf("s1: %v\n", s1)
}

执行结果如下

---删除之前---
s1: [1 2 3 4]
---删除之后---
s1: [1 2 4]

删除元素的公式

要从切片a中删除索引为index的元素,操作方法如下

a = append(a[:index], a[index+1:]...)

3. 修改切片元素

package main
 
import "fmt"
 
func main() {
    var s1 = []int{1, 2, 3, 4, 5}
    s1[1] = 100 //索引1的值改为100
    fmt.Printf("s1: %v\n", s1)
}

输出结果如下

s1: [1 100 3 4 5]

4. 查找切片元素

package main
 
import "fmt"
 
func main() {
    var s1 = []int{1, 2, 3, 4, 5}
    var key = 2 //查找2所在的位置
    for i, v := range s1 {
        if v == key {
            fmt.Printf("s1: %v\n", s1)
            fmt.Printf("索引为: %v\n", i)
        }
    }
}

输出结果如下

s1: [1 2 3 4 5]
索引为: 1

5. 拷贝切片

package main
 
import "fmt"
 
func main() {
    var s1 = []int{1, 2, 3, 4, 5}
    var s2 = s1
    s2[0] = 100
    fmt.Printf("s1: %v\n", s1)
    fmt.Printf("s2: %v\n", s2)
}

输出结果如下

s1: [100 2 3 4 5]
s2: [100 2 3 4 5]

可以看到当s2的值改变的时候,s1的值也改变了,因为s2复制了s1的是他的内存地址,所以相关联都会改变

使用copy方法修改则不会对源切片的值有影响

package main
 
import "fmt"
 
func main() {
    var s1 = []int{1, 2, 3, 4, 5}
    var s2 = make([]int, 4) //需要make一个切片的类型,指定有5个元素
    copy(s2, s1)    //指定复制的切片
 
    s2[0] = 100
    fmt.Printf("s1: %v\n", s1)
    fmt.Printf("s2: %v\n", s2)
}

输出结果

s1: [1 2 3 4 5]
s2: [100 2 3 4 5]

到此这篇关于Go语言实现切片增删改查的示例代码的文章就介绍到这了!


Tags in this post...

Golang 相关文章推荐
goland 恢复已更改文件的操作
Apr 28 Golang
Go语言中break label与goto label的区别
Apr 28 Golang
golang 接口嵌套实现复用的操作
Apr 29 Golang
go类型转换及与C的类型转换方式
May 05 Golang
解决goland 导入项目后import里的包报红问题
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
go web 预防跨站脚本的实现方式
Jun 11 Golang
go select编译期的优化处理逻辑使用场景分析
Jun 28 Golang
Go 语言中 20 个占位符的整理
Oct 16 Golang
Go 中的空白标识符下划线
Mar 25 Golang
Golang解析JSON对象
Apr 30 Golang
Go语言测试库testify使用学习
Jul 23 Golang
Golang 结构体数据集合
Apr 22 #Golang
Golang map映射的用法
Apr 22 #Golang
Golang bufio详细讲解
Apr 21 #Golang
Go获取两个时区的时间差
Apr 20 #Golang
Golang jwt身份认证
实现GO语言对数组切片去重
Apr 20 #Golang
Golang日志包的使用
Apr 20 #Golang
You might like
Yii分页用法实例详解
2014/12/04 PHP
PHP实现将MySQL重复ID二维数组重组为三维数组的方法
2016/08/01 PHP
PHP设计模式(四)原型模式Prototype实例详解【创建型】
2020/05/02 PHP
JS Timing
2007/04/21 Javascript
js实现弹窗插件功能实例代码分享
2013/12/12 Javascript
JS将所有对象s的属性复制给对象r(原生js+jquery)
2014/01/25 Javascript
JQuery实现防止退格键返回的方法
2015/02/12 Javascript
浅析JavaScript Array和string的转换(推荐)
2016/05/20 Javascript
jQuery Validate插件实现表单验证
2016/08/19 Javascript
JavaScript类的写法
2016/09/17 Javascript
javascript操作cookie
2017/01/17 Javascript
Webpack打包慢问题的完美解决方法
2017/03/16 Javascript
node.JS md5加密中文与php结果不一致的解决方法
2017/05/05 Javascript
修改 bootstrap table 默认detailRow样式的实例代码
2017/07/21 Javascript
浅谈Node Inspector 代理实现
2017/10/19 Javascript
详解基于React.js和Node.js的SSR实现方案
2019/03/21 Javascript
4 种滚动吸顶实现方式的比较
2019/04/09 Javascript
如何利用vue+vue-router+elementUI实现简易通讯录
2019/05/13 Javascript
JavaScript进阶(二)词法作用域与作用域链实例分析
2020/05/09 Javascript
小程序中手机号识别的示例
2020/12/14 Javascript
浅谈Python NLP入门教程
2017/12/25 Python
python中自带的三个装饰器的实现
2019/11/08 Python
tensorflow 实现自定义梯度反向传播代码
2020/02/10 Python
python 双循环遍历list 变量判断代码
2020/05/04 Python
Python descriptor(描述符)的实现
2020/11/15 Python
Anya Hindmarch官网:奢侈设计师手袋及配饰
2018/11/15 全球购物
日本热销NO.1胶原蛋白冻:Aishitoto爱希特多
2019/06/20 全球购物
Brora官网:英国领先的羊绒服装品牌
2019/08/28 全球购物
捷克多品牌在线时尚商店:ANSWEAR.cz
2020/10/03 全球购物
接口的多继承会带来哪些问题
2015/08/17 面试题
党支部公开承诺书
2014/03/28 职场文书
2014年党风廉政建设工作总结
2014/11/19 职场文书
故意伤害人身损害赔偿协议书
2014/11/19 职场文书
保安2014年终工作总结
2014/12/06 职场文书
入党介绍人意见怎么写
2015/06/03 职场文书
windows下快速安装nginx并配置开机自启动的方法
2021/05/11 Servers