Go slice:切片的“陷阱”和本质
文章说明
总结了go语言中切片slice的特殊性和使用时的注意事项。
个人理解,不足之处欢迎指出。
slice:切片,是go语言中一种常用的数据结构,基于数组构建,表示相同数据类型的集合。
数组
Go中数组类型表示固定长度的相同类型的数据的集合,数据在内存中连续存储,可以通过下标索引,但是又有特殊的地方:
- 数组是值类型,一个数组变量表示整个数组,而不是指向数组的首元素的指针,这和C语言不同。
- 将数组赋值给另一个数组,或者数组作函数参数传递时,会将数组的全部数据拷贝一份过去而不是传递一个指针。
- 数组类型包括长度,即[5]int和[10]不是一种类型。
所以Go语言中使用数组传递数据效率很低,通常使用切片。
切片
切片是一个数组片段的描述,包含了指向数组片段的指针,片段的长度len和容量cap(数组片段的最大长度),但是切片本身并不是真正的指针类型。
切片的特性
- 可以自动扩容
使用append()向切片追加数据,数据是被添加到切片指向的片段末尾,长度等于容量时切片就会自动扩容,扩容的细节后面的文章再讨论。 - 切片之间赋值或者切片作函数参数传递时,是将指向数组片段的指针传递过去,所以改变一个会影响另一个。
切片的陷阱
切片作函数参数传递或浅拷贝时,之所以改变一个切片的数据会影响另一个切片,是因为两个切片中中包含了指向同一数组片段的指针。
一切看似正常?但是当一个切片发生扩容时,会将当前切片内的数据复制到另一片内存区域,该切片的数组片段的地址发生改变,所以当切片扩容时修改一个切片的数据时不会再影响到另一个切片!此时只能通过传递切片本身的地址来解决。
扩容时出错的代码如下:
package main
import "fmt"
func testSlice(slice []int) {
slice = append(slice, 6, 7, 8, 9, 10)
fmt.Println("testSlice:",slice)
}
func main() {
slice := []int{1, 2, 3, 4, 5}
testSlice(slice)
fmt.Println("main:",slice)
}
切片的本质
可以证明,切片不是指针类型,切片数据类型是包含指向一个数组片段的指针,和当前数组片段的长度,以及当前数组最大容量的一种复合数据结构。
想深入了解Go中slice数据类型的底层实现,可以参考本人实现slice的源代码自己动手实现Go切片数据结构
Go slice:切片的“陷阱”和本质的更多相关文章
- golang:slice切片
一直对slice切片这个概念理解的不是太透彻,之前学习python的就没搞清楚,不过平时就用python写个工具啥的,也没把这个当回事去花时间解决. 最近使用go开发又遇到这个问题,于是打算彻底把这个 ...
- golang slice切片的原理以及内置函数cap, len
golang中slice(切片)是常用的类型, slice是对数组进行封装 package main import ( "fmt" "strconv") fun ...
- python定制类(1):__getitem__和slice切片
python定制类(1):__getitem__和slice切片 1.__getitem__的简单用法: 当一个类中定义了__getitem__方法,那么它的实例对象便拥有了通过下标来索引的能力. c ...
- golang基础---Slice切片
切片Slice在go语言中是单独的类型(指向底层的数组),不同于python(对可迭代对象操作的工具),注意区分数组和slice的区别 定义一个空slice,格式var s []int,这种既没有长度 ...
- Go语言核心之美 3.2-slice切片
Slice(切片)是长度可变的元素序列(与之相应,上一节中的数组是不可变的),每一个元素都有同样的类型.slice类型写作[]T.T是元素类型.slice和数组写法非常像,差别在于slice没有指定长 ...
- Go - Slice 切片
概述 切片是一种动态数组,比数组操作灵活,长度不是固定的,可以进行追加和删除. len() 和 cap() 返回结果可相同和不同. 声明切片 //demo_7.go package main impo ...
- Go(03) slice切片的使用
原文链接 http://www.limerence2017.com/2019/05/08/golang05/#more golang 的引用类型和内置类型变量 golang 中变量类型分为引用类型和值 ...
- 3.9 Go Slice切片
3.9 Go Slice切片 Go语言切片(Slice) 切片是可动态变化的序列,是对数组的引用,引用类型,遵循引用传递的机制 slice类型写作[ ]T,T是slice元素类型,var s1 []i ...
- go语言笔记——切片底层本质是共享数组内存!!!绝对不要用指针指向 slice切片本身已经是一个引用类型就是指针
切片 切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型) ...
随机推荐
- chromedriver配置
需要先安装chrome浏览器,添加chrome源 sudo vim /etc/yum.repos.d/google-chrome.repo 添加以下内容 [google-chrome] name=go ...
- centos7安装apache http server启动失败--Failed to start The Apache HTTP Server.
centos7安装apache http server启动失败 除了nginx可以开启http服务外,apche http server也可以开启http服务,安装过程如下:1. 首先,检测是 ...
- 2. 2.1查找命令——linux基础增强,Linux命令学习
2.1.查找命令 grep命令 grep 命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并 把匹配的行打印出来. 格式: grep [option] pattern [file] 可使用 ...
- ZooKeeper入门(四) Zookeeper监视(Watches)
1 简介 Zookeeper 所有的读操作——getData(), getChildren(), 和 exists() 都 可以设置监视(watch),并且这些watch都由写操作来触发:create ...
- js random获取随机数,获取任意范围内随机整数
壹 ❀ 引 想着好久没做笔试题了,去GitHub找了面试相关的项目,结果被第一道题难住了.....说难其实也不难,而是我忘记了取范围随机整数怎么写了,不可否认如果当时是我在笔试,肯定也凉了,那么就由 ...
- 17.Linux命令
1.网络配置 setup 配置 ifup eth0 启动网卡 文件保存在 /etc/sysconfig/network-scripts/ifcfg-eth0,修改ifcfg-eth0配 ...
- 1. UML软件设计模型图整理
UML建模 程序设计ER图 UML建模(一)---UserCase用例图 UML建模(二)--流程图 (程序框图) UML建模(三)--部署图 UML建模(四)--类图 UML用例图.流程图 (五)
- Loadrunner基本概念解析<一>
学习性能测试前需要掌握的基本概念,以下做一个记录,本文会持续更新,我期望的是,用通俗简洁的语言来进行更好的理解. [基本概念如下:] ---并发用户数: 1️⃣错误的理解: 使用系统的全部用户数 ...
- 个人永久性免费-Excel催化剂功能第66波-数据快速录入,预定义引用数据逐字提示
在前面好几波的功能中,为数据录入的规范性做了很大的改进,数据录入乃是数据应用之根,没有完整.干净的数据源,再往下游的所有数据应用场景都是空话.在目前IT化进程推进了20多年的现状,是否还仍有必要在Ex ...
- Java多线程(七):ReentrantLock
加锁和解锁 我们来看下ReentrantLock的基本用法 ThreadDomain35类 public class ThreadDomain35 { private Lock lock = new ...