Go语言切片Slice的使用
2022/6/13 23:22:04
本文主要是介绍Go语言切片Slice的使用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1、来源于数组的切片
package main import "fmt" func main() { a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //添加了...表示数组 b := a[2:6] //切片 fmt.Println(b) //[3 4 5 6] 左包右不包 }
可以省略开始,可以省略结束,可以省略开始和结束
package main import "fmt" func main() { a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //数组 b := a[2:6] //切片 fmt.Println(b) //[3 4 5 6] 左包右不包 c := a[:6] //可以省略开始 fmt.Println(c) //[1 2 3 4 5 6] d := a[2:] //可以省略结束 fmt.Println(d) //[3 4 5 6 7 8] e := a[:] //可以省略开始和结束 fmt.Println(e) //[1 2 3 4 5 6 7 8] }
2、切片slice是数组的视图
改变切片的元素,底层数组也会改变
package main import "fmt" func update(a []int) { a[0] = 100 a[1] = 1000 } func main() { a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //数组 b := a[2:6] //切片是数组的视图 查看数组的第2到第6个元素 fmt.Println(b) //[3 4 5 6] 左包右不包 src := a[:] //底层数组a的全部视图 fmt.Println(fmt.Sprintf("原始的底层数组全视图是:%d", src)) update(src) fmt.Println(fmt.Sprintf("改变了切片后的底层数组全视图是:%d", src)) fmt.Println(fmt.Sprintf("原始的底层数组是:%d", a)) }
3、slice可以继续reslice
package main import "fmt" func update(a []int) { a[0] = 100 a[1] = 1000 } func main() { a := []int{1, 2, 3, 4, 5, 6, 7, 8} //[]中没有...代表切片 b := a[2:7] //切片可以再次切片,称为reslice fmt.Println(b) //[3 4 5 6 7] c := b[3:] fmt.Println(c) //[6 7] d := c[:1] fmt.Println(d) //[6] }
4、slice会向底层看齐
如果切片时,切片到头了,则会向底层查看一下是否还有可视的值,因为切片是数组的视图,所以最终会视图到最底层的数组,例如
package main import "fmt" func main() { arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8} fmt.Println(fmt.Sprintf("底层数组:%d", arr)) s1 := arr[2:6] fmt.Println(fmt.Sprintf("arr[2:6]:%d", s1)) // s1 是 [3 4 5 6] 如果再对s1取3:5,则会出来什么呢 s2 := s1[3:5] fmt.Println(fmt.Sprintf("s1[3:5]:%d", s2)) //会出来[6 7] 6是来自于切片s2 而7是来自于底层数组arr }
可以看出s1都没有s1[4]而s2取出来了7,这是由于视图向下看,看到了底层数组的7
说明:
数组arr是1,2,3,4,5,6,7,8
s1 := arr[2:6] 是取数组的第三个元素,总共取4个元素,就是3,4,5,6,但是s1是知道数组arr还有7,8两个元素,因为s1是数组的视图
s2 := s1[3:5]是取s1的第四个元素,总共去2个元素,第一个元素就是6,但是第二个元素在s2中没有了,如果打印s2[4]则会报错,但是因为是视图,s1是知道后面的元素是7,8,因此第二个元素就可以取到7,如果再取一个元素,那就是可以取到8,如果再取一个,因为底层数组到8便没有了,因此抛出异常
5、切片slice的底层数据结构
说明
①slice由ptr和len以及cap组成
②ptr
是指针,指向切片的第一个元素
③len
是切片的长度,从ptr开始到结束的元素个数,当下标 超过这个长度后会报下标越界的错误
④cap
表示切片的容量,表示共可以存多少个元素,当添加元素后,如果容量不够,会自动扩容
⑤slice可以向后扩展,不可以向前扩展,扩展可以超过len的值,但不能超过底层数组的cap
打印切片的len和cap
package main import "fmt" func main() { arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8} fmt.Println(fmt.Sprintf("底层数组:%d", arr)) s1 := arr[2:6] fmt.Println(fmt.Sprintf("arr[2:6]:%d, len:%d, cap:%d", s1, len(s1), cap(s1))) // s1 是 [3 4 5 6] 如果再对s1取3:5,则会出来什么呢 s2 := s1[3:5] fmt.Println(fmt.Sprintf("s1[3:5]:%d, len:%d, cap:%d", s2, len(s2), cap(s2))) //会出来[6 7] 6是来自于切片s2 而7是来自于底层数组arr }
6、slice添加元素
使用append添加元素,添加的元素会紧跟在后面,添加后多余cap的数据会被挤出去
append方式作用于底层数组
package main import "fmt" func main() { arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 6 7] s1 := arr[2:6] fmt.Println(fmt.Sprintf("s1:%d", s1)) //[2 3 4 5] s2 := s1[3:4] fmt.Println(fmt.Sprintf("s2:%d", s2)) //[5] s3 := append(s2, 10) fmt.Println(fmt.Sprintf("s3:%d", s3)) //[5 10] // 由于s2是[5] append后10直接跟着5后面,把6给直接顶掉了 //因为slice是底层数组的view,即是底层数组的视图,所以append作用于底层数组 //底层中的5后面的数6就被10给替换了 fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 10 7] s4 := append(s3, 11) //[5 10 11] fmt.Println(fmt.Sprintf("s4:%d", s4)) //由于s3是[5 10],直接append一个11,因此11直接跟在10后面,原来底层数组10后面是7,因此把7给替换成了11 fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 10 11] s5 := append(s4, 12) //[5 10 11 12] fmt.Println(fmt.Sprintf("s5:%d", s5)) //由于s4是[5 10 11]直接append一个12,因此12直接跟在11后面,但是由于再跟一个12,就超过了底层数组的cap,因此会产生一个新的地址存放新的数据 //如果用debug的方式查看,就能看到产生了新的地址存放新的数组 fmt.Println(fmt.Sprintf("底层数组:%d", arr)) }
debug方式查看新的地址存放新数据
7、slice的几种创建方式
- var定义slice
package main import "fmt" func main() { var s []int//申明切片s,默认是nil fmt.Println(fmt.Sprintf("var 定义的 slice默认值:%v", s)) for i := 0; i < 100; i++ { s = append(s, i)//通过append方式添加元素 fmt.Println(fmt.Sprintf("len:%d cap:%d, value:%d", len(s), cap(s), s)) } //可以看到cap会默认自己扩张 }
- 冒号:定义slice
package main import "fmt" func main() { s := []int{2, 4, 6, 8, 10} fmt.Println(fmt.Sprintf("len:%d, cap:%d, value:%d", len(s), cap(s), s)) }
- make关键字创建slice
如果想创建某个长度的slice可以使用make函数
例如:我想创建cap为10的slice,但我只知道其中5个
package main import "fmt" func main() { s := make([]int, 5, 10) s[0] = 10 s[1] = 1 s[2] = 10 s[3] = 1 s[4] = 10 fmt.Println(fmt.Sprintf("len:%d, cap:%d, value:%d", len(s), cap(s), s)) }
- copy关键字创建slice
package main import "fmt" func main() { s := []int{1, 2, 3, 5} fmt.Println(s) s1 := []int{0, 0, 0}//[1 2 3 5] [1 2 3] copy(s1, s) fmt.Println(s, s1) }
8、删除slice元素
删除中间的元素
package main import "fmt" func main() { s := []int{1, 2, 3, 4, 5} fmt.Println(s) s1 := append(s[:2], s[3:]...)//移除3 fmt.Println(s1) }
删除首元素
package main import "fmt" func main() { s := []int{1, 2, 3, 4, 5} fmt.Println(s) s1 := s[1:] fmt.Println(s1) }
删除尾巴元素
package main import ( "fmt" ) func main() { s := []int{1, 2, 3, 4, 5} fmt.Println(s) s1 := s[:len(s)-1] fmt.Println(s1) }
这篇关于Go语言切片Slice的使用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。
- 2024-10-20goland工具下,如修改一个项目的标准库SDK的版本-icode9专业技术文章分享
- 2024-10-17Go学习:初学者的简单教程
- 2024-10-17Go学习:新手入门完全指南