go切片的概念及用法
发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,这篇文章主要介绍"go切片的概念及用法",在日常操作中,相信很多人在go切片的概念及用法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"go切片的概念及用法"的疑惑有所帮
千家信息网最后更新 2025年01月25日go切片的概念及用法
这篇文章主要介绍"go切片的概念及用法",在日常操作中,相信很多人在go切片的概念及用法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"go切片的概念及用法"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
go切片原型
// runtime/slice.gotype slice struct { array unsafe.Pointer// 引用底层数组的指针 len int// 引用数组元素的长度,使用下标对元素进行访问的时候,下标不能超过len cap int // 引用数组的容量,cap>=len}
定义一个名为baseSlice 的切片
baseSlice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
底层结构
定义一个新的切片slice1
slice1 := baseSlice[2:5] //[]int{2,3,4}
底层结构
定义一个新的切片slice2
slice2 := slice1[4:7] //[]int{6,7,8}
底层结构
源码
package mainimport ("fmt")func main() {baseSlice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}slice1 := baseSlice[2:5] //[]int{2,3,4} //这里slice1 cap是8,底层引用的数组为[]int{2, 3, 4, 5, 6, 7, 8, 9} //所以slice1 len=3, cap=8 //由于 slice1 cap=8 所以slice1[4:7]并不会发生数组越界 slice2 := slice1[4:7] //[]int{6,7,8} fmt.Printf("slice1:%v.len:%d.cap:%d\n", slice1, len(slice1), cap(slice1)) //slice1:[2 3 4].len:3.cap:8 fmt.Printf("slice2:%v.len:%d.cap:%d\n", slice2, len(slice2), cap(slice2)) //slice2:[6 7 8].len:3.cap:4}
切片是值传递
package mainimport ("fmt")func main() {baseSlice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}slice1 := baseSlice[2:5] //[]int{2,3,4} appendSlice(slice1)fmt.Printf("slice1:%v\n", slice1) //slice1:[2 3 4] fmt.Printf("baseSlice:%v\n", baseSlice) //baseSlice:[0 1 2 3 4 10 6 7 8 9]}func appendSlice(s []int) { //值传递 s = append(s, 10) //这里会改变底层数组里的值,如果append的元素个数大于底层引用数组的容量,则会触发一次数组copy fmt.Printf("append slice1:%v\n", s) //append slice1:[2 3 4 10]}
引用传递的假象
如果在调用的方法里,修改了传入切片len内的值,导致底层数组对应的值被修改,从调用方法外看,就像传入的切片值被修改了。
package mainimport ("fmt")func main() {baseSlice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}slice1 := baseSlice[2:5] //[]int{2,3,4} appendSlice(slice1)fmt.Printf("slice1:%v\n", slice1) //slice1:[123 3 4],看起来是slice1被修改了,其实是由于底层数组被修改的缘故 fmt.Printf("baseSlice:%v\n", baseSlice) //baseSlice:[0 1 123 3 4 5 6 7 8 9]}func appendSlice(s []int) { //值传递 // s = append(s, 10) s[0] = 123 //这里会改变底层数组里的值 fmt.Printf("append slice1:%v. len=%d. cap=%d\n", s, len(s), cap(s)) //append slice1:[123 3 4]. len=3. cap=8}
深度copy
package mainimport ("fmt")func main() {baseSlice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}slice1 := baseSlice[4:7] //[]int{6,7,8} fmt.Printf("slice1:%v\n", slice1) //slice1:[4 5 6] //slice 深copy slice2 := make([]int, 3, 3)copy(slice2, slice1)fmt.Printf("slice2:%v. len=%d. cap=%d\n", slice2, len(slice2), cap(slice2)) //slice2:[4 5 6]. len=3. cap=3 slice2[0] = 100fmt.Printf("slice2:%v\n", slice2) //slice2:[100 5 6] fmt.Printf("slice1:%v\n", slice1) //slice1:[4 5 6] fmt.Printf("baseSlice:%v\n", baseSlice) //baseSlice:[0 1 2 3 4 5 6 7 8 9]}
扩容
// runtime/slice.go//cap 为满足存放数据的最小容量func growslice(et *_type, old slice, cap int) slice { ... if cap > doublecap { newcap = cap } else { if old.len < 1024 {//如果slice len<1024,扩容时容量增长2倍,也就是2个变4个 newcap = doublecap } else {//如果slice len>=1024,扩容时增加原来容量的四分之一 // Check 0 < newcap to detect overflow // and prevent an infinite loop. for 0 < newcap && newcap < cap {newcap += newcap / 4 } ... } }
nil slice和empty slice
empty slice 底层数组指针指向实际存在的空数组的地址;
nil slice 底层数组指针指向的是nil;
package mainimport ( "fmt")func main() { var nilSlice []int emptySlice := make([]int, 0) if emptySlice == nil { fmt.Println("emptySlice is nil.") } if nilSlice == nil { fmt.Println("nilSlice is nil.") //输出 nilSlice is nil. }}
tips:
Go 语言的函数参数传递,只有值传递。
到此,关于"go切片的概念及用法"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!
数组
底层
容量
学习
元素
指针
方法
结构
下标
指向
更多
帮助
实用
最小
接下来
个数
假象
函数
原型
参数
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
星能服务器主板
安全资源池服务器
达索软件开发实验室
集成测试中客户服务器集成的特点
软件开发加盟
网络技术相关视频
武装突袭三服务器介绍
软件开发税务筹划技巧与实务
网络安全读物
用户对数据库的操作模板
网络安全法对产品和服务
多媒体平台与网络技术
2018网络安全微视频展映
rust查看服务器时间
vgpu服务器搭建
泰拉瑞亚怎么通过服务器连接
网站设计是不是软件开发
steam如何建立服务器
软件开发职业生涯规划作文
公司内部服务器管理设置
obs 云服务器直播
陕西农业科研课题项目软件开发
求应聘软件开发工作
优秀黑板报网络安全记心中
八大投行数据库
kettle监测数据库状态
天龙八部手游服务器虎啸神州
微软如何协调软件开发人员
全球网络安全软件
tsql 创建数据库