GO 语言中 slice 理解

为什么说 Go 语言的 slice 是引用类型,其底层实现明明是一个结构体?

slice 的底层实现是一个包含三个字段的结构体:指向底层数组的指针、slice 的长度和 slice 的容量。当我们对 slice 进行操作时,例如添加或删除元素,实际上是在底层数组中进行操作。由于 slice 是一个指向底层数组的指针,因此多个 slice 可以共享同一个底层数组,这也是 slice 被称为引用类型的原因,也因此可以将其赋值为 nil(实际上是将底层结构体中的指向底层数组的指针设置为 nil)。

需要注意的是,虽然 slice 是引用类型,但是它并不是一个指针类型。因此,我们可以对 slice 进行赋值和传递,而不需要使用指针。这也是 Go 语言中 slice 的一个优点,它可以方便地进行传递和复制,而不需要担心底层数组的复制和传递带来的性能问题。

除了 slice,Go 语言中还有其他的引用类型,例如 map 和 channel

函数调用中修改 slice 的元素会影响原 slice 吗?

这里要分具体情况,如果在函数中对 slice 进行了 append 操作导致了 slice 扩容,那么扩容之后的 slice 的底层数据与原 slice 分离,就不会相互影响,否则会影响原 slice

//  初始化一个长度和容量不相同的 slice,函数中 append 操作没有导致底层数据扩容
// 所以对 slice[0] 的修改会影响原 slice
func Test_isSliceChangeIfAppend(t *testing.T) {
    slice := make([]int, 5, 10)
    fmt.Printf("origin slice:%v\n", slice)
    isSliceChangeIfAppend(slice)
    fmt.Printf("after append out func:%v\n", slice)
} func isSliceChangeIfAppend(origin []int) {
    origin = append(origin, 1, 2, 3)
    origin[0] = 1
    fmt.Printf("after append in func:%v\n", origin)
} -----output-----
origin slice:[0 0 0 0 0]
after append in func:[1 0 0 0 0 1 2 3]
after append out func:[1 0 0 0 0]
//  同上面的代码,初始化一个长度和容量相同的 slice
// 函数中的 append 操作就一定会扩容,后续修改也就不会影响原 slice
func Test_isSliceChangeIfAppend(t *testing.T) {
// 初始化一个长度和容量相同的 slice
slice := make([]int, 5)
fmt.Printf("origin slice:%v\n", slice)
isSliceChangeIfAppend(slice)
fmt.Printf("after append out func:%v\n", slice)
} func isSliceChangeIfAppend(origin []int) {
origin = append(origin, 1, 2, 3)
origin[0] = 1
fmt.Printf("after append in func:%v\n", origin)
} -----output-----
origin slice:[0 0 0 0 0]
after append in func:[1 0 0 0 0 1 2 3]
after append out func:[0 0 0 0 0]

![图片](https://mmbiz.qpic.cn/mmbiz_png/2fBauyxIV9YmLFQeheVRlib675c1S34fYGl7Y1RGmdwISIncPcibic1phDVRPaqUZKJUCx0lINWdqtWcJOpArFsKA/640?wx_fmt=png)

GO 语言中 slice 的理解的更多相关文章

  1. Go语言中slice使用注意事项

    Go 语言中的slice类型可以理解为是数组array类型的描述符,包含了三个因素: 指向底层数组的指针 slice目前使用到的底层数组的元素个数,即长度 底层数组的最大长度,即容量 因此当我们定义一 ...

  2. 对C语言中static的理解

    对C语言中的static关键字的深入理解 在一次面试的时候面试官问我static全局变量与全局变量的区别,之前虽然用过但是并没仔细去搞懂他,这次来细心的学习一下. 基本概念 使用static有三种情况 ...

  3. Go语言中slice作为参数传递时遇到的一些“坑”

    前言 相信看到这个题目,可能大家都觉得是一个老生常谈的月经topic了.一直以来其实把握一个"值传递"基本上就能理解各种情况了,不过最近遇到了更深一点的"小坑" ...

  4. c语言中pthread的理解和使用

    在头文件中看到#typedef unsigned long int pthread_t这句话怎么理解,pthread_t是一个什么类型呢? 相当于pthread_t实际是个unsigned long  ...

  5. Go语言中的slice

    Go语言中的slice有点类似于Java中的ArrayList,但在使用上更加灵活,先通过下面一个小例子来体验一下如何通过一个已有的切片来产生一个新切片: func main() { slice := ...

  6. [转]理解Go语言中的nil

    最近在油管上面看了一个视频:Understanding nil,挺有意思,这篇文章就对视频做一个归纳总结,代码示例都是来自于视频. nil是什么 相信写过Golang的程序员对下面一段代码是非常非常熟 ...

  7. C语言中malloc函数的理解

    在C语言中malloc函数主要是用在堆内存的申请上,使用malloc函数时,函数会返回一个void *类型的值,这个值就是你申请的堆内存的首地址:为什么返回的地址是一个void *类型的地址呢?首先我 ...

  8. C语言中,头文件和源文件的关系(转)

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...

  9. C语言中的static 详细分析

    转自:http://blog.csdn.net/keyeagle/article/details/6708077/ google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇大 ...

  10. C语言中void*详解及应用

    void在英文中作为名词的解释为“空虚:空间:空隙”:而在C语言中,void被翻译为“无类型”,相应的void *为“无类型指针”.void似乎只有“注释”和限制程序的作用,当然,这里的“注释”不是为 ...

随机推荐

  1. [软件测试]Web接口的性能测试

    1 接口响应性能影响因素分析 影响Web接口查询响应性能的重要因素: 1.网络/带宽.服务器硬件资源(CPU.内存.磁盘) 2.用户并发数 3.查询的基础数据集的量级.百万级?亿级?百亿级? 4.查询 ...

  2. systemctl 命令设置开机自启动失败

    哈喽大家好,我是咸鱼.今天跟大家分享一个关于 Linux 服务(service)相关的案例   案例现象 我在 3 月 31日的时候发表了一篇<shell 脚本之一键部署安装 Nginx> ...

  3. Java设计模式 —— 建造者模式

    8 建造者模式 8.1 建造者模式概述 Builder Pattern:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式可以将部件本身和它们的组装过程分开,关注如 ...

  4. servlet 没有实例化可以直接调用非静态方法??

    今天练习servlet时,居然发现没有实例化可以直接调用非静态方法.看了好长时间发现:省去了this关键字.记录一下. public class Servlet2 extends GenericSer ...

  5. 08列表(list)与元组(tuple)

    列表(list)与元组(tuple) 列表的格式 >- [数据1,数据2,数据3,数据4,......] >- 列表可以存储多个数据,数据之间的逗号以英文分割而且可以数据是不同类型的数据, ...

  6. MySQL(四)用户与权限管理

    用户与权限管理 用户管理 MySQL用户分为普通用户和root用户,提供了许多语句来管理包括登录.退出MySQL服务器.创建用户.删除用户.密码管理和权限管理等内容. 登录MySQL服务器 mysql ...

  7. 一款能“干掉” ChatGPT 的应用「GitHub 热点速览」

    据说有了它,ChatGPT 就可以靠边站了.因为 Auto-GPT 能更加主动地完成你给他的指定任务,不用做更多的人为干涉,它的推理能力比 ChatGPT 更强,有人用它解放双手做了个 React 网 ...

  8. SpringCloud导入spring boot项目当作子模块微服务IDEA不识别子module问题

    1.在父工程下面引入module. <modules> <module>study-design-mode</module> </modules> 2. ...

  9. java Stack(栈)类、Queue和Deque队列

    1. java Stack类 特性是:LIFO(后进先出)先进后出,最先进入的在栈底. Stack底层也是通过数组实现的,同时也是线程安全的 Stack stack=new Stack(); //添加 ...

  10. Java 网络编程 —— 创建多线程服务器

    一个典型的单线程服务器示例如下: while (true) { Socket socket = null; try { // 接收客户连接 socket = serverSocket.accept() ...