Go 切片:用法和本质

embedded/2025/1/24 8:07:31/

要想更好的了解一个知识点,实战是最好的经历。

题目

我这里放一道题目:

package mainimport "fmt"func SliceRise(s []int) {s = append(s, 0)for i := range s {s[i]++}fmt.Println(s)
}func SlicePrint() {s1 := []int{1, 2}s2 := s1s2 = append(s2, 3)SliceRise(s1)SliceRise(s2)fmt.Println(s1, s2)
}func main() {SlicePrint()
}

大家猜猜本题的运行结果是多少?

s1: 1、2          ||          s2:2、3、4

知识点

是不是蒙了( •̀ ω •́ )✧,蒙了才有效果,才能更加明白自己的不足。

以上涉及了好几个知识点。我一一讲起。

1、切片的底层数据结构

type Slice struct{array   unsafe.Pointer // 储存着数组存放地址len     int            // 切片长度cap     int            // 切片容量
}

切片的底层数据结构是一个 “结构体"

2、切片的扩容机制

slice的扩容遵循以下原则

1、如果slice容量小于1024,则新slice容量扩大为原来的2倍。

2、如果slice容量大于等于1024,采用1.25倍,则新的slice容量将扩大为原来的1.25倍

这里有一点需要注意,当slice扩容时,会开辟一个新的空间,将旧的slice依次复制进入。

以上是 Go 1.17 版本的策略,随着go的更新迭代,仍会有调整,但不会偏离以上太多。


学到这里,其实就已经基本OK了,接下来我会放出本题的解析。

解析

大家都知道,切片是引用传递。什么是引用传递呢?就是传递地址值。

但是有一点需要注意,切片的数据结构是结构体,底层是struct。

所以传递时,将会创造一个新的结构体,把老结构体全部粘贴复制进去(地址,len、cap)

s1 := s2

如上,就相当于

相当于把两个结构体,直接复制并拷贝过去复制了一个一模一样的。

显而易见,这两个,是不同的结构体。--> 但是却共同一个共同的地址0111,也就是同一个数组。

到这里大家应该就明白了,他们传递时,传递的是地址。结构体是直接复制过去的一个新的。

s = append(s,0)时,由于新添加了一个值,导致容量扩大,cap增加。这时就会分配一个新地址给s结构体。而原来的s1结构体内,存的地址不会改变。

故fmt.Println(s1)是:1、2。

而s2,用同样的分析,亦可得出结论。

参考:

《GO专家编程》


http://www.ppmy.cn/embedded/156519.html

相关文章

什么是生成式大模型?大模型与生成式大模型的区别?

生成式大模型(Large Generative Models)是指具有大量参数的人工智能模型,它们能够生成新的内容,如文本、图片、音乐等。这类模型通常基于深度学习技术,尤其是神经网络,能够捕捉到数据的复杂分布&#xff0c…

《从入门到精通:蓝桥杯编程大赛知识点全攻略》(五)-数的三次方根、机器人跳跃问题、四平方和

本博客将详细探讨如何通过二分查找算法来解决这几个经典问题。通过几个实际的例子,我们将展示如何在这些问题中灵活应用二分查找,优化计算过程,并在面对大数据量时保持高效性。 目录 前言 数的三次方根 算法思路 代码如下 机器人跳跃问题…

go学习杂记

一些学习时候留下的杂技,单纯用来记录,想要系统学习的话还是要看书籍哈 2025/1/21 面向对象原则 依赖倒置原则:高层模块依赖于抽象,而不是具体实现。(高层不依赖底层,而是依赖抽象接口。这样随时可以切换选…

Cursor的详细使用指南

以下是一份关于 Cursor 的详细使用指南: 一、安装与设置 下载与安装: 首先,访问 Cursor 的官方网站,根据你的操作系统(Windows、Mac 或 Linux)下载相应的安装程序。运行安装程序,按照屏幕上的提…

洛谷刷题1-3

比较巧妙,求最小公倍数,看多少个数一次循环,直接求解就好了,N的数量级比较大,一层循环也会超时,也用了点双指针的想法(归并排序) 这里很大的问题,主要是cin输入的时候遇到…

lwIP——3 内存管理

目录 1.什么是内存管理 2.lwIP内存堆 3.lwIP内存堆程序代码解析 3.1 mem_init程序解析 3.2 mem_malloc程序解析 3.3 mem_free程序解析 4.lwIP内存池 5.lwIP内存池程序代码解析 5.1 实现lwIP内存池的文件 5.1.1 memp_priv.h 5.1.2 memp_std.h 5.1.3 memp.h memp_t 枚…

路由器缓冲区如何调节的指南说明

调整路由器缓冲区大小是一个复杂且需要细致操作的过程,涉及到对网络流量、设备性能以及缓冲区类型的深入理解。本位作为一篇详尽的指南,提供调整路由器缓冲区的具体方法。 一、前期准备与评估 1. 了解路由器型号与操作系统: 不同品牌和型号…

【Redis】在Java中以及Spring环境下操作Redis

Java环境下&#xff1a; 1.创建maven 项目 2.导入依赖 <!-- redis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.2</version></dependency> 此处使用的是Jedis&…