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 相关文章推荐
golang 如何用反射reflect操作结构体
Apr 28 Golang
go设置多个GOPATH的方式
May 05 Golang
浅谈golang package中init方法的多处定义及运行顺序问题
May 06 Golang
golang 实现时间戳和时间的转化
May 07 Golang
Golang 获取文件md5校验的方法以及效率对比
May 08 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
Go Plugins插件的实现方式
Aug 07 Golang
Golang流模式之grpc的四种数据流
Apr 13 Golang
golang使用map实现去除重复数组
Apr 14 Golang
实现GO语言对数组切片去重
Apr 20 Golang
Golang 并发编程 SingleFlight模式
Apr 26 Golang
在ubuntu下安装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生成月历代码
2007/06/14 PHP
php与paypal整合方法
2010/11/28 PHP
PHP动态分页函数,PHP开发分页必备啦
2011/11/07 PHP
深入php函数file_get_contents超时处理的方法详解
2013/06/03 PHP
IIS下PHP的三种配置方式对比
2014/11/20 PHP
Yii控制器中操作视图js的方法
2016/07/04 PHP
php版微信公众平台开发之验证步骤实例详解
2016/09/23 PHP
PHP微信支付结果通知与回调策略分析
2019/01/10 PHP
一些Javascript的IE和Firefox(火狐)兼容性的问题总结及常用例子
2009/05/21 Javascript
Js实现自定义右键行为
2015/03/26 Javascript
在JavaScript中访问字符串的子串
2015/07/07 Javascript
javascript实现根据3原色制作颜色选择器的方法
2015/07/17 Javascript
jQuery UI设置固定日期选择特效代码分享
2015/08/27 Javascript
Vue.js每天必学之构造器与生命周期
2016/09/05 Javascript
js将table的每个td的内容自动赋值给其title属性的方法
2016/10/13 Javascript
localStorage实现便签小程序
2016/11/28 Javascript
Vue常用指令V-model用法
2017/03/08 Javascript
详解如何将angular-ui的图片轮播组件封装成一个指令
2017/05/09 Javascript
用jquery获取select标签中选中的option值及文本的示例
2018/01/25 jQuery
js实现购物车功能
2018/06/12 Javascript
Vant的安装和配合引入Vue.js项目里的方法步骤
2018/12/05 Javascript
在VUE中实现文件下载并判断状态的方法
2019/11/08 Javascript
[01:59]深扒TI7聊天轮盘语音出处 1
2017/05/11 DOTA
[40:17]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第一场
2018/04/06 DOTA
python实现各进制转换的总结大全
2017/06/18 Python
Pytorch在dataloader类中设置shuffle的随机数种子方式
2020/01/14 Python
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例
2016/02/28 HTML / CSS
Bibloo匈牙利:女装、男装、童装及鞋子和配饰
2019/04/14 全球购物
Antonioli美国在线商店:时尚前卫奢华
2019/07/29 全球购物
2014年计算机专业个人自我评价
2014/01/19 职场文书
服装设计专业自荐信
2014/06/17 职场文书
扶贫办主任查摆“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书
2014教师专业技术工作总结
2014/12/03 职场文书
Python Django 后台管理之后台模型属性详解
2021/04/25 Python
Django cookie和session的应用场景及如何使用
2021/04/29 Python
Nginx利用Logrotate实现日志分割
2022/05/20 Servers