Go切片深入学习

Go切片专项学习

go切片扩容机制

go1.18 之前:

1.如果期望容量大于当前容量的两倍就会使用期望容量;

2.如果当前切片的长度小于 1024 就会将容量翻倍;

3.如果当前切片的长度大于 1024 就会每次增加 25% 的容量,直到新容量大于期望容量;

go1.18 之后:

1.如果期望容量大于当前容量的两倍就会使用期望容量;

2.如果当前切片的长度小于阈值(默认 256)就会将容量翻倍;

3.如果当前切片的长度大于等于阈值(默认 256),就会每次增加 25% 的容量,基准是 newcap + 3*threshold,直到新容量大于期望容量;

第一条相同,新扩容机制在长度小于256以下时,扩容机制仍然和旧的一样,不同的是,当大于256的时候扩容会按照指定的公式进行扩容。

最后求极限扩容系数会趋近于1.25。

这样做的目的是为了控制让小的切片容量增长速度快一点,减少内存分配次数,而让大切片容量增长率小一点,更好地节省内存。

前几天朋友让我看了一道题:挺有意思的,短短几行代码就把切片的性质说的一清二楚。

go 复制代码
package main

import "fmt"

func SliceRise(s []int) {
    s = append(s, 0)
    fmt.Printf("s = %v\n", s)
    for i := range s {
       s[i]++
    }
}

func main() {
    s1 := []int{1, 2}
    s2 := s1
    s2 = append(s2, 3)
    SliceRise(s1)
    SliceRise(s2)
    fmt.Printf("s1 = %v\n", s1)
    fmt.Printf("s2 = %v\n", s2)
}

这个代码输出结果是:

复制代码
s = [1 2 0]
s = [1 2 3 0]
s1 = [1 2]   
s2 = [2 3 4] 

我们看看为什么?

首先,第一个s由于扩容,导致了底层数组改变,所以方法内和方法外是两个不同的结构,

第二个s在方法外就已经扩容了,进入方法内后底层数组指针仍然没有改变,这就是关键点了,既然没有改变,为什么内部是长度为4,外侧就为3了呢?

肯定会有很多人认为最后结果是2341 。

原因就在于切片是值传递的,传递进去的是原始切牌的拷贝,进入后新切片长度为4,容量为4,而在外侧的切片长度为3,容量为4,这就导致了只能输出前三位。

相关推荐
Yang-Never1 小时前
Kotlin协程 -> Job.join() 完整流程图与核心源码分析
android·开发语言·kotlin·android studio
知识分享小能手2 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
TomCode先生3 小时前
c#动态树形表达式详解
开发语言·c#
高-老师3 小时前
基于R语言的物种气候生态位动态量化与分布特征模拟
开发语言·r语言·物种气候
大翻哥哥4 小时前
Python 2025:量化金融与智能交易的新纪元
开发语言·python·金融
weixin_437830944 小时前
使用冰狐智能辅助实现图形列表自动点击:OCR与HID技术详解
开发语言·javascript·ocr
鹿鹿学长5 小时前
2025年全国大学生数学建模竞赛(C题) 建模解析|婴儿染色体数学建模|小鹿学长带队指引全代码文章与思路
c语言·开发语言·数学建模
zhousenshan5 小时前
Python爬虫常用框架
开发语言·爬虫·python
茯苓gao5 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾5 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang