golang中,slice的几个易混淆点
slice在golang中是最常用的类型,一般可以把它作为数组使用,但是比数组要高效呀。不过,我感觉这个东西用的不好坑太多了。还是需要了解下他底层的实现
slice的结构定义
type slice struct {
array unsafe.Pointer
len int
cap int
}
看结构定义,就三个字段,那个指针指向的就是底层数组,所以说slice的底层结构就是数组。
slice的声明
第一种方式
var s []int #和数组差不多,[]中间不要数字
第二种方式
s :=[]int{}
第三种方式
s :=make([]int,len,cap)
len 表示元素的实际数量
cap 表示可以容纳元素的最大个数
以上三种定义是有区别的,第一种定义的s值为nil slice,其它两种为empty slice.要编码时要加以区分
slice扩容逻辑
- 如果slice容量足够容纳新增的元素,那么不会扩容。
- 如果新增元素后容量不足,则会扩容为原容量的 2 倍大小,如果原 slice 容量大于1024,那扩容后的容量等于每次扩容前增加 1/4。同时将原来的数据拷贝到新的数组中,所以还是要合理使用扩容。
slice的几个混淆点
一、slice作参数传递
slice作参数传递时,虽然是值传递(拷贝一份),但是slice的内部指针,指向的还是同一个数组是引用,所以会有影响。
func main() {
var s []int
for i := 1; i <= 4; i++ {
s = append(s, i)
}
fmt.Println("原始s的值",s)
changeslice(s)
fmt.Println("s被改变后的值", s)
}
func changeslice(s []int) {
s[0] = 7
s[1] = 8
fmt.Println("changeslice后的s值", s)
}
输出:
原始s的值 [1 2 3 4]
changeslice后的s值 [7 8 3 4]
s被改变后的值 [7 8 3 4]
二、使用append,无扩容
继续上面的,这次在函数里面加上append;
append后,生成的新的slice。但是因为没有扩容,指向的还是同一个数组,所以还是会影响到原来的slice
func main() {
var s []int
for i := 1; i <= 3; i++ {
s = append(s, i)
}
fmt.Println("原始s的值",s)
changeslice(s)
fmt.Println("s被改变后的值", s)
}
func changeslice(s []int) {
s = append(s,777)
s[1] = 999
fmt.Println("changeslice后的s值", s)
}
输出:
原始s的值 [1 2 3]
changeslice后的s值 [1 999 3 777]
s被改变后的值 [1 999 3]
三、继续append,有扩容
这次继续使用append,不过这次多appen几个元素,
发现如果扩容后,那么生成的新slice就不会影响到原来的了,因为
指向的不是原来的数组
func main() {
var s []int
for i := 1; i <= 3; i++ {
s = append(s, i)
}
fmt.Println("原始s的值",s)
changeslice(s)
fmt.Println("s被改变后的值", s)
}
func changeslice(s []int) {
s = append(s,777,888)
s[1] = 999
fmt.Println("changeslice后的s值", s)
}
输出:
原始s的值 [1 2 3]
changeslice后的s值 [1 999 3 777 888]
s被改变后的值 [1 2 3]
通过slice切割生成slice
从slice切割生成的slice,其实还是指向的同一个底层数组,一方有改动,还是会影响到对方。
var s []int
s = []int{1,2,3,4,5,6}
fmt.Println("原始的s的值", s)
s2 :=s[1:5]
fmt.Println("切割后的:s2", s2)
s2[0] = 99
fmt.Println("s2重新赋值:",s2)
fmt.Println("s的值:", s)
s3 :=s2[0:2]
fmt.Println("s3的值", s3)
s3[1] = 99999
fmt.Println("s2的值",s2)
fmt.Println("s的值",s)
输出:
原始的s的值 [1 2 3 4 5 6]
切割后的:s2 [2 3 4 5]
s2重新赋值: [99 3 4 5]
s的值: [1 99 3 4 5 6]
s3的值 [99 3]
s2的值 [99 99999 4 5]
s的值 [1 99 99999 4 5 6]
总结
平时使用slice时,还是要小心点,主要注意有无扩容这块。不然就会产生很多不可想像的问题了。
golang中,slice的几个易混淆点的更多相关文章
- 说说不知道的Golang中参数传递
本文由云+社区发表 导言 几乎每一个C++开发人员,都被面试过有关于函数参数是值传递还是引用传递的问题,其实不止于C++,任何一个语言中,我们都需要关心函数在参数传递时的行为.在golang中存在着m ...
- C#中一些易混淆概念总结
C#中一些易混淆概念 这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框 ...
- C#中易混淆的知识点
C#中易混淆的知识点 一.引言 今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为:http://social.msdn.microsoft.com/Forums/zh-CN/52e6 ...
- lua中易混淆函数
lua中易混淆的函数 ipairs和pairs: ipairs只能顺序遍历table,遇到key不是数字就会退出 pairs可以遍历table中所有元素 ----------------------- ...
- JavaScript中易混淆的DOM属性及方法对比
JavaScript中易混淆的DOM属性及方法对比 ParentNode.children VS Node.prototype.childNodes ParentNode.children:该属性继承 ...
- 【C#小知识】C#中一些易混淆概念总结(七)---------解析抽象类,抽象方法
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------继承 分类: C# 2014-02-06 22:05 1106人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------深入解析C#继承
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
随机推荐
- PHP面试题2019年百度工程师面试题及答案解析
一.单选题(共10题,每题5分) 1.以下代码输出的结果是? A.[0,1,2,3] B.[1,3,5,7,5] C.[1,2,3,4,5] D.[0,1,2,3,5] 参考答案:D 答案解析 ...
- Dynamics CRM 2015/2016新特性之七:有了文档模板,打印分析So Easy
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复190或者20160216可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 从CRM 2015 UR1开始, ...
- iOS中的GCD线程
一.什么是GCD 全称是Grand Central Dispatch ,纯C语言编写,提供非常多强大的函数,是目前苹果官网推荐的多线程开发方法,NSOperation 便是基于GCD的封装 ...
- SoapUI、Postman测试WebService
之前装了SoapUI,最近装了Postman,分别用它们测试了WebService,下面为用法. 测试的在线WebService(数据来源于中国气象局)Endpoint: http://www.web ...
- 本地Yum源配置
一.网络源 yum list 软件名称 查找源里的软件,可以使用通配符 二.配置源 源配置文件路径 /etc/yum.repos.d/ 配置项 [名称] 源标识(不能和其他的源重复) name=名称 ...
- CentOS7打开、关闭防火墙。
CentOS7 以上机器一些命令和低版本CentOS是有些差异的,本文只针对CentOS7 以上版本. CentOS7使用firewalld打开关闭防火墙与端口1.firewalld的基本使用启动: ...
- spark Streaming与kafka的集成消费
Spark 2.3.3 Kafka 2.11-1.0.2 Java jdk1.8.0_191 Hbase 1.2.11 from pyspark impo ...
- luoguP5227 [AHOI2013]连通图
题意 虽然没用线段树,但是仍然是线段树分治的思想. 考虑分治询问序列,假设当前在\([l,r]\),我们将\([1,l-1]\)和\([r+1,Q]\)的与\([l,r]\)内不重复的边都连上了. 先 ...
- Unity 插件宝典 (张忠喜 廖一庭 著)
第1章 模型类插件 第2章 特效类插件 第3章 动画插件 第4章 编辑器插件 第5章 脚本类插件 第6章 GUI插件 第7章 Shaders插件 第8章 优化类插件 第9章 综合应用----卡通版赛车 ...
- 【搜索】N皇后问题
原题传送门 思路 很经典的搜索题,但本蒟蒻卡了1个多小时,搜索部分很简单,但是判重的部分是真的蛋疼,我写了一个高效率的判重算法,但是无论检查多少遍都没有问题的算法却总是WA......后来我干脆写了一 ...