文章说明

总结了go语言中切片slice的特殊性和使用时的注意事项。

个人理解,不足之处欢迎指出。

slice:切片,是go语言中一种常用的数据结构,基于数组构建,表示相同数据类型的集合。

数组

Go中数组类型表示固定长度的相同类型的数据的集合,数据在内存中连续存储,可以通过下标索引,但是又有特殊的地方:

  • 数组是值类型,一个数组变量表示整个数组,而不是指向数组的首元素的指针,这和C语言不同。
  • 将数组赋值给另一个数组,或者数组作函数参数传递时,会将数组的全部数据拷贝一份过去而不是传递一个指针。
  • 数组类型包括长度,即[5]int和[10]不是一种类型。

所以Go语言中使用数组传递数据效率很低,通常使用切片。

切片

切片是一个数组片段的描述,包含了指向数组片段的指针,片段的长度len和容量cap(数组片段的最大长度),但是切片本身并不是真正的指针类型

切片的特性

  1. 可以自动扩容

    使用append()向切片追加数据,数据是被添加到切片指向的片段末尾,长度等于容量时切片就会自动扩容,扩容的细节后面的文章再讨论。
  2. 切片之间赋值或者切片作函数参数传递时,是将指向数组片段的指针传递过去,所以改变一个会影响另一个。

切片的陷阱

切片作函数参数传递或浅拷贝时,之所以改变一个切片的数据会影响另一个切片,是因为两个切片中中包含了指向同一数组片段的指针。

一切看似正常?但是当一个切片发生扩容时,会将当前切片内的数据复制到另一片内存区域,该切片的数组片段的地址发生改变,所以当切片扩容时修改一个切片的数据时不会再影响到另一个切片!此时只能通过传递切片本身的地址来解决。

扩容时出错的代码如下:

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:切片的“陷阱”和本质的更多相关文章

  1. golang:slice切片

    一直对slice切片这个概念理解的不是太透彻,之前学习python的就没搞清楚,不过平时就用python写个工具啥的,也没把这个当回事去花时间解决. 最近使用go开发又遇到这个问题,于是打算彻底把这个 ...

  2. golang slice切片的原理以及内置函数cap, len

    golang中slice(切片)是常用的类型, slice是对数组进行封装 package main import ( "fmt" "strconv") fun ...

  3. python定制类(1):__getitem__和slice切片

    python定制类(1):__getitem__和slice切片 1.__getitem__的简单用法: 当一个类中定义了__getitem__方法,那么它的实例对象便拥有了通过下标来索引的能力. c ...

  4. golang基础---Slice切片

    切片Slice在go语言中是单独的类型(指向底层的数组),不同于python(对可迭代对象操作的工具),注意区分数组和slice的区别 定义一个空slice,格式var s []int,这种既没有长度 ...

  5. Go语言核心之美 3.2-slice切片

    Slice(切片)是长度可变的元素序列(与之相应,上一节中的数组是不可变的),每一个元素都有同样的类型.slice类型写作[]T.T是元素类型.slice和数组写法非常像,差别在于slice没有指定长 ...

  6. Go - Slice 切片

    概述 切片是一种动态数组,比数组操作灵活,长度不是固定的,可以进行追加和删除. len() 和 cap() 返回结果可相同和不同. 声明切片 //demo_7.go package main impo ...

  7. Go(03) slice切片的使用

    原文链接 http://www.limerence2017.com/2019/05/08/golang05/#more golang 的引用类型和内置类型变量 golang 中变量类型分为引用类型和值 ...

  8. 3.9 Go Slice切片

    3.9 Go Slice切片 Go语言切片(Slice) 切片是可动态变化的序列,是对数组的引用,引用类型,遵循引用传递的机制 slice类型写作[ ]T,T是slice元素类型,var s1 []i ...

  9. go语言笔记——切片底层本质是共享数组内存!!!绝对不要用指针指向 slice切片本身已经是一个引用类型就是指针

    切片 切片(slice)是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型) ...

随机推荐

  1. ThinkPHP判断post,get操作

    define('REQUEST_METHOD',$_SERVER['REQUEST_METHOD']); define('IS_GET', REQUEST_METHOD =='GET' ? true ...

  2. python算法与数据结构-数据结构中常用树的介绍(45)

    一.树的定义 树是一种非线性的数据结构,是由n(n >=0)个结点组成的有限集合.如果n==0,树为空树.如果n>0,树有一个特定的结点,根结点根结点只有直接后继,没有直接前驱.除根结点以 ...

  3. Jenkins与RocketChat集成

    Jenkins与RocketChat集成 在Jenkins中安装插件RocketChat Notifier 配置信息 点击Jenkins左侧的系统管理-->系统设置, 找到Global Rock ...

  4. CentOS 7编译安装Redis

    安装编译相关依赖 CentOS/Fedora yum install gcc gcc-c++ cmake tcl 下载Redis源码包 curl -o redis-4.0.10.tar.gz http ...

  5. Nginx查看并发连接数

    Nginx查看并发连接 通过界面查看 通过界面查看通过web界面查看时Nginx需要开启status模块,也就是安装Nginx时加上 --with-http_stub_status_module 然后 ...

  6. C++类的完美单元测试方案——基于C++11扩展的friend语法

    版权相关声明:本文所述方案来自于<深入理解C++11—C++11新特性解析与应用>(Michael Wong著,机械工业出版社,2016.4重印)一书的学习. 项目管理中,C语言工程做单元 ...

  7. 03_javaSE面试题:类初始化和实例初始化

    题目 下面代码运行的结果是什么? Father 类 /** * @author kevin * @date 2019/7/8 15:48 */ public class Father { privat ...

  8. java虚拟机-GC-GC算法

    在C/C++中是由程序员自己去申请.管理和释放内存的,因此没有GC的概念.而在Java中,专门有一个用于垃圾回收的后台线程来进行监控.扫描,自动将一些无用的内存进行释放.下面介绍几种常见的GC算法. ...

  9. HDU 4819:Mosaic(线段树套线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=4819 题意:给出一个矩阵,然后q个询问,每个询问有a,b,c,代表(a,b)这个点上下左右c/2的矩形区域内的( ...

  10. HDU 5773:The All-purpose Zero(贪心+LIS)

    http://acm.hdu.edu.cn/showproblem.php?pid=5773 The All-purpose Zero Problem Description   ?? gets an ...