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. Django后端 服务器找不到template(路径问题)

    Django后端 服务器找不到template(路径问题) 该代码在本地跑没有任何问题, 但是上传到服务器上报错找不到模板或者模板不存在. 看网页最下方报错(一定要看报错!!)显示路径有问题 问题原因 ...

  2. [Linux]CentOS7:创建OS用户+授予sudo权限

    1 创建OS用户+授予sudo权限 Step1 下载安装Xshell.Xftp工具 Step2 通过Xshell,远程登陆服务器root用户 Step3 使用检查用户的命令查询当前linux环境是否存 ...

  3. JUC(三)集合的线程安全

    目录 集合的线程安全 list集合线程不安全演示 Vector解决 Collections.synchronizedList JUC 解决方案:CopyOnWriteArrayList HashSet ...

  4. javasec(八)jndi注入

    JNDI JNDI(全称Java Naming and Directory Interface)是用于目录服务的Java API,它允许Java客户端通过名称发现和查找数据和资源(以Java对象的形式 ...

  5. 学习MASA第一天:MASA Blazor TEST项目创建

    个人博客地址: https://note.raokun.top 拥抱ChatGPT,国内访问网站:https://www.playchat.top 学习MASA第一天:MASA Blazor TEST ...

  6. Lambda表达式和链式编程

    一.Lambda表达式 1. Lambda使用条件 Lambda表达式是 JDK8 的一个新特性,可以认为是对匿名内部类的一种简化,但不是所有的匿名内部类都可以简化为Lambda表达式. 只有函数式接 ...

  7. maven下载和配置信息

    1. 下载maven: https://maven.apache.org/ 2. 进入官网点击 Download 3. 最新版直接下载 .tar.gz 格式linux系统 .zip windows系统 ...

  8. StarRocks 3.0 集群安装手册

    本文介绍如何以二进制安装包方式手动部署最新版 StarRocks 3.0集群. 什么是 StarRocks StarRocks 是新一代极速全场景 MPP (Massively Parallel Pr ...

  9. ES6 新增的一些特性

    还有symbol和set,map, bind,call,apply 1. let关键字 (1)基本用法:let关键字用来声明变量,它的用法类似于var,都是用来声明变量. (2)块级作用域:let声明 ...

  10. 使用require.context实现优雅的预加载

    前言 在前端开发中,对页面花里胡哨度[注1]要求越高的页面,用到的图片.音频什么的就越多,比如什么结婚请柬.展会请柬.发布会宣传页.数据大屏.虽然现在浏览器不允许网页在没有用户交互的情况下播放音频,但 ...