深入了解Golang中Slice切片的使用
作者:nil 发布时间:2023-09-25 08:59:08
写在前面
周日下午在家学习,看到一个关于切片的问题,在网上找了一些资料,做个总结。
上代码
func main() {
sl := make([]int, 0, 10)
var appenFunc = func(s []int) {
s = append(s, 10, 20, 30)
fmt.Println(s, len(sl), cap(sl))
}
fmt.Println(sl, len(sl), cap(sl))
appenFunc(sl)
fmt.Println(sl, len(sl), cap(sl))
fmt.Println(sl[:10], len(sl), cap(sl))
fmt.Println(sl[:], len(sl), cap(sl))
}
你觉得会输出什么?思考一下再往下看。
有的人觉得可能是
[] 0 10
[10 20 30] 3 10
[] 0 10
[] 0 10
[] 0 10
实际结果是
[] 0 10
[10 20 30] 0 10
[] 0 10
[10 20 30 0 0 0 0 0 0 0] 0 10
[] 0 10
是不是差别很大?这里的差别主要是第四行、第五行的结果。
第一行:比较好理解,切片没有做任何修改,值应该是:[] 0 10
第二行:也很好理解,在appendFunc函数中打印sl,结果是:[10 20 30] 3 10 第三行:由于go都是值传递,所以传到appendFunc函数中的sl其实是切片复制了一份,对原sl没有影响,所以输出结果是:[] 0 10
第四行:sl[:10]这个应该会报数组越界错误才对?怎么没有报错,而且还输出了10 20 30,但是len(sl)等于0,很奇怪
第五行:如果第四行能输出整个数组的内容,这里的sl[:]应该也能输出内容,但是为什么是空的?
分析原因
这里有2个问题:
为什么sl[0:10]能输出10个元素,并且打印出了函数中添加的元素?但是len(sl)等于0
为什么sl[:]输出空数组?
大家都知道,slice(切片)的底层实现,slice 底层存储的数据结构指向了一个 array(数组),如下图:
slice结构体定义如下
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
Data:指向具体的底层数组。
Len:代表切片的长度。
Cap:代表切片的容量。
核心要记住的是:slice 真正存储数据的地方,是一个数组。slice 的结构中存储的是指向所引用的数组指针地址。
看到这里你应该明白了,传入到appendFunc函数的sl虽然是外层定义的sl的一个值拷贝,它的修改不会影响原sl的内容,但是由于Data是个指针,appendFunc函数对Data的修改自然就影响了原sl的Data,这个很好理解。
要记住一个关键点:如果传过去的值是指向内存空间的地址,是可以对这块内存空间做修改的
对于第一个问题:为什么sl[0:10]能输出10个元素?
这里跟切片访问的一个优化有关,当用s[low : high]访问切片的时候,表达式 s[low : high]
中的 high,最大的取值范围对应着切片的容量(cap),不是单纯的长度(len) 。因此调用 fmt.Println(sl[:10])
时可以输出容量范围内的值,不会出现越界。
相对的 fmt.Println(sl)
, fmt.Println(sl[:])
因为该切片 len 值为 0,没有指定最大索引值,high 则取 len 值,导致输出结果为空。
来源:https://juejin.cn/post/7188838658081259557
猜你喜欢
- 如代码1所示: // 代码 1 // 外观层类 class LWordHomePage { // 添加留言 public function
- 今日大致浏览了一下《High Performance Web Sites》。本书的中文版是《高性能网站建设指南》。本书另有对其中个别问题深入
- 在Windows环境下,经常遇到系统Over的情况,如果你在新装了系统和SQL Server 2005后,需要把SQL Server2000
- 是的,这仅仅是一个PPT文档,由Anna Debenham上传至slideshare。幻灯片的标题叫做《CSS nuggets》,嗯,很好的
- 有些时候(如开发聊天程序),我们需要将将滚动条(scrollbar)保持在最底部,比如聊天窗口,最新发出和收到的信息要显示在最下方,如果要看
- js表单验证只能是写限定的东西大收集 代码如下:ENTER键可以让光标移到下一个输入框<input onkeydown=&q
- 功能: 1、 允许/限制对表的修改 2、 自动生成派生列,比如自增字段 3、 强制数据一致性 4、 提供审计和日志记录 5、 防止无效的事务
- 写这段代码的原因是昨天项目中遇到的一个问题。一同事要求 写一个效果要求鼠标掠过表格行该行颜色改变以突出显示。这个倒不难,那哥们直接为每个Tr
- 还是一个关于checkbox的一个普通的效果,就是根据你勾选的checkbox,列出你选择了哪些值演示代码:<!DOCTYPE htm
- 这个我早就改好了一直没有放上来.现在发给大家用用注意这几个变量它们影响到提示框的效果代码:var rT=true;//允许图像过渡
- 上个月,我写了一篇关于微软如何在向jQuery贡献代码的文章,也谈到了在第一批贡献的代码中的一些功能:jQuery模板和数据链接支持.今天,
- 本文实例讲述了python函数局部变量用法。分享给大家供大家参考。具体分析如下:当你在函数定义内声明变量的时候,它们与函数外具有相同名称的其
- 在oracle中有很多关于日期的函数,如:1、add_months()用于从一个日期值增加或减少一些月份 date_value:=add_m
- 导航是网页设计的重点,我们在设计一个网站的时候,常常从导航入手,不夸张的说,导航的设计甚至决定了整个网站的风格。这就需要我们平常多留心收集优
- 1:在终端下:mysql -V。 以下是代码片段:[shengting@login ~]$ mysql -Vmysql Ver 14.7 D
- 最近碰到一个mysql5数据库的问题。就是一个标准的servlet/tomcat网络应用,后台使用mysql数据库。问题是待机一晚上后,第二
- js 代码中经常会碰到 undefined 这种错误,下面本文分享一下为什么会发生这种错误以及如何处理这种错误,js 中如果通过 var 声
- 一、日期类型:对于SQL Server 2008 来说(因为2000甚至2005已经稍微有被淘汰的迹象,所以在此不作过多说明,加上自己工作使
- 一、'建立register.asp 代码如下:<%@ language=vbscript %>&nb
- asp之字符串函数示例用字符串函数对字符串进行截头去尾、大小写替换等操作。函数语 * 能LenLen(string|varname)返回字符串