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 相关文章推荐
Go语言中的UTF-8实现
Apr 26 Golang
golang 如何通过反射创建新对象
Apr 28 Golang
golang 在windows中设置环境变量的操作
Apr 29 Golang
解决golang post文件时Content-Type出现的问题
May 02 Golang
Golang标准库syscall详解(什么是系统调用)
May 25 Golang
Golang并发操作中常见的读写锁详析
Aug 30 Golang
golang实现一个简单的websocket聊天室功能
Oct 05 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
Go并发4种方法简明讲解
Apr 06 Golang
Go语言grpc和protobuf
Apr 13 Golang
Go gRPC进阶教程gRPC转换HTTP
Jun 16 Golang
Go语言编译原理之源码调试
Aug 05 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
php 获取本机外网/公网IP的代码
2010/05/09 PHP
ThinkPHP结合ajax、Mysql实现的客户端通信功能代码示例
2014/06/23 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
PHP面向对象程序设计之构造方法和析构方法详解
2019/06/13 PHP
javascript setAttribute, getAttribute 在不同浏览器上的不同表现
2010/08/05 Javascript
js调用webservice中的方法实现思路及代码
2013/02/25 Javascript
JS随机漂浮广告代码具体实例
2013/11/19 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
2014/04/06 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
浅谈JavaScript数据类型
2015/03/03 Javascript
浅谈 Vue 项目优化的方法
2017/12/16 Javascript
vue动态绑定组件子父组件多表单验证功能的实现代码
2018/05/14 Javascript
JS中的const命令你真懂它吗
2020/03/08 Javascript
举例讲解Linux系统下Python调用系统Shell的方法
2015/11/07 Python
Python读取视频的两种方法(imageio和cv2)
2018/04/15 Python
python打包生成的exe文件运行时提示缺少模块的解决方法
2018/10/31 Python
Python模块的加载讲解
2019/01/15 Python
解决python文件双击运行秒退的问题
2019/06/24 Python
Django生成PDF文档显示在网页上以及解决PDF中文显示乱码的问题
2019/07/04 Python
Python转换字典成为对象,可以用&quot;.&quot;方式访问对象属性实例
2020/05/11 Python
Expected conditions模块使用方法汇总代码解析
2020/08/13 Python
HTML5之tabindex属性全面解析
2016/07/07 HTML / CSS
Cotton On美国网站:澳洲时装连锁品牌
2016/10/25 全球购物
J2EE的优越性主要表现在哪些方面
2016/03/28 面试题
营销与策划个人求职信
2013/09/22 职场文书
九月份红领巾广播稿
2014/01/22 职场文书
幼儿园母亲节活动方案
2014/03/10 职场文书
收款授权委托书
2014/10/02 职场文书
乡镇团委工作总结2015
2015/05/26 职场文书
小学生家长意见
2015/06/03 职场文书
警示教育观后感
2015/06/17 职场文书
劳保用品管理制度范本
2015/08/06 职场文书
导游词之平津战役纪念馆
2019/11/04 职场文书
写一个Python脚本自动爬取Bilibili小视频
2021/04/24 Python
python之基数排序的实现
2021/07/26 Python
docker 制作mysql镜像并自动安装
2022/05/20 Servers