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扩容逻辑

  1. 如果slice容量足够容纳新增的元素,那么不会扩容。
  2. 如果新增元素后容量不足,则会扩容为原容量的 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的几个易混淆点的更多相关文章

  1. 说说不知道的Golang中参数传递

    本文由云+社区发表 导言 几乎每一个C++开发人员,都被面试过有关于函数参数是值传递还是引用传递的问题,其实不止于C++,任何一个语言中,我们都需要关心函数在参数传递时的行为.在golang中存在着m ...

  2. C#中一些易混淆概念总结

    C#中一些易混淆概念 这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框 ...

  3. C#中易混淆的知识点

    C#中易混淆的知识点 一.引言 今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为:http://social.msdn.microsoft.com/Forums/zh-CN/52e6 ...

  4. lua中易混淆函数

    lua中易混淆的函数 ipairs和pairs: ipairs只能顺序遍历table,遇到key不是数字就会退出 pairs可以遍历table中所有元素 ----------------------- ...

  5. JavaScript中易混淆的DOM属性及方法对比

    JavaScript中易混淆的DOM属性及方法对比 ParentNode.children VS Node.prototype.childNodes ParentNode.children:该属性继承 ...

  6. 【C#小知识】C#中一些易混淆概念总结(七)---------解析抽象类,抽象方法

    目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...

  7. 【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏

    目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...

  8. 【C#小知识】C#中一些易混淆概念总结(五)---------继承 分类: C# 2014-02-06 22:05 1106人阅读 评论(0) 收藏

    目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...

  9. 【C#小知识】C#中一些易混淆概念总结(五)---------深入解析C#继承

    目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...

随机推荐

  1. uni-app学习(四)好用的插件2

    1. uni-app学习(四)好用的插件2 1.1. 树形结构 点击这里 1.2. 下拉刷新上拉加载组件 如果想把下拉上拉做成自定义的,更加好看,可以使用这个插件 地址这里 举个例子 1.3. 浮动键 ...

  2. 从0系统学Android-2.1Activity的使用

    更多精品文章分类 第二章:先从看的到的入手-Activity 上一章成功创建了自己的第一个项目.这一章从页面入手,来进行学习. 2.1 Activity 是什么 Activity 是一种可以包含用户界 ...

  3. Nginx的负载均衡算法、lvs的负载均衡算法

    NGINX: 官方默认的算法: RR:轮询 weight:权重 ip_hash:配置此项后weight项失效 第三方模块: fair:根据后端服务器的繁忙程度 url_hash:如果客户端访问的url ...

  4. C语言异常处理

    异常的概念-程序在运行过程中可能产生异常-异常(Exception)与Bug的区别 异常是程序运行时可预料的执行分支 Bug是程序中的错误,是不被预期的运行方式 异常(Exception)和Bug的对 ...

  5. Selenium WebDriver 中鼠标事件(全)

    Selenium WebDriver 中鼠标事件(全) 鼠标点击操作  鼠标点击事件有以下几种类型:  清单 1. 鼠标左键点击   Actions action = new Actions(driv ...

  6. wafer2-nodejs 本地部署服务器

    友情提示:假设你已经部署好了腾讯云微信小程序服务,如果没有,就不用往下看了,果断选云开发. ------------------------------------------------------ ...

  7. Python网络编程基础 ❶ 计算机网络基础 初用socket模块

    1.计算机网络基础 C/S  客户端/服务器端 B/S  浏览器端/服务器端 mac地址,ip地址,子网掩码,与计算得到网段,端口号每台计算机的网卡都有全球唯一的地址,在生产时已经写进去了. ip地址 ...

  8. 微信小程序云开发-从0打造云音乐全栈小程序

    第1章 首门小程序“云开发”课程,你值得学习本章主要介绍什么是小程序云开发以及学习云开发的重要性,并介绍项目的整体架构,真机演示项目功能,详细介绍整体课程安排.课程适用人群以及需要掌握的前置知识.通过 ...

  9. linux的命令操作

    linux的命令操作 1.日常操作命令 **查看当前所在的工作目录pwd **查看当前系统的时间 date **查看有谁在线(哪些人登陆到了服务器)who 查看当前在线last 查看最近的登陆历史记录 ...

  10. 物联网架构成长之路(41)-直播流媒体入门(RTSP篇)

    1. 搭建RTSP服务 首先现在音视频利器 ffmpeg,这个到http://www.ffmpeg.org/download.html 这里下载压缩包即可. 文档参考:http://trac.ffmp ...