☰
【Go语言基础【17】】切片:一种动态数组
2026/11/3 18:25:23 网站建设 项目流程

文章目录

  • 零、概述
  • 一、切片基础
    • 1、切片的结构
    • 2、切片的创建方式
    • 3、切片的操作与扩容
  • 二、切片的拷贝与共享内存
  • 三、切片作为函数参数

Go语言的切片(slice)是一种动态数组,提供了灵活、高效的元素序列操作。它基于底层数组实现,通过长度和容量的分离设计,支持动态扩容和内存优化。

零、概述

切片 vs 数组

特性切片(slice)数组(array)
类型引用类型值类型
长度动态可变固定不可变
传递方式传递指针副本,修改影响原数据传递值拷贝,修改不影响原数据
创建方式make([]T, len, cap)或[]T{...}[n]T{...}或[...]T{...}
内存占用包含指针、长度、容量仅包含元素

性能优化原理:

  1. 预分配容量:若已知元素数量,使用make([]T, 0, capacity)避免频繁扩容。
  2. 避免内存泄漏:切片保留对底层数组的引用,若仅需部分元素,建议copy到新切片后释放原数组。
  3. 大容量切片谨慎扩容:大切片扩容可能导致内存浪费,可通过copy手动控制扩容策略。

一、切片基础

1、切片的结构

切片是一个引用类型,底层结构包含三个字段:

typeslicestruct{array unsafe.Pointer// 指向底层数组的指针lenint// 当前切片的长度capint// 底层数组的容量}
  • 长度(len):切片中实际存在的元素数量,可通过len()函数获取。
  • 容量(cap):底层数组的总长度,可通过cap()函数获取。
  • 指针(array):指向底层数组的起始位置,决定了切片的起始元素。

示例:创建切片

s:=make([]int,3,5)// 创建长度为3、容量为5的切片// 底层数组: [0, 0, 0, 0, 0]// 切片结构: {array: 指向数组, len: 3, cap: 5}

2、切片的创建方式

a.使用make函数

s1:=make([]int,3)// 长度=容量=3,初始值为0s2:=make([]int,3,5)// 长度=3,容量=5

b.使用切片字面量

s3:=[]int{1,2,3}// 长度=容量=3,初始值为[1,2,3]s4:=[]int{3:100}// 索引3的值为100,长度=容量=4,初始值为[0,0,0,100]

c.从数组或切片派生

arr:=[5]int{1,2,3,4,5}s5:=arr[1:3]// 从数组创建切片,[2,3],长度=2,容量=4s6:=s5[0:2]// 从切片创建切片,[2,3],长度=2,容量=4

3、切片的操作与扩容

a.访问元素
通过索引访问,范围为0到len(s)-1:

s:=[]int{1,2,3}fmt.Println(s[0])// 输出: 1

b.基于切片创建切片
通过指定[low:high:max]创建新切片:

  • low:起始索引(包含)。
  • high:结束索引(不包含),新切片长度为high - low。
  • max:容量上限,新切片容量为max - low(可选,默认等于原切片容量)。
s:=[]int{10,20,30,40,50}s1:=s[1:3]// 长度=2,容量=4,元素=[20,30]s2:=s[1:3:3]// 长度=2,容量=2,元素=[20,30]

c.nil切片与空切片

varnilSlice[]int// nil切片,array=nil,len=0,cap=0emptySlice:=make([]int,0)// 空切片,array指向空数组,len=0,cap=0
  • nil切片:未初始化,array为nil。
  • 空切片:已初始化,但长度为0,array指向底层数组。

d.动态扩容:append函数

s:=make([]int,0,2)// 容量=2s=append(s,1,2)// 追加元素,容量足够,直接添加s=append(s,3)// 容量不足,触发扩容(通常翻倍)

扩容规则:

  • 容量<1000时,通常翻倍。
  • 容量≥1000时,按1.25倍增长(具体实现可能随版本变化)。

e、多维切片
切片的元素可以是另一个切片,形成多维结构:

matrix:=[][]int{{1,2,3},{4,5,6},}fmt.Println(matrix[0][1])// 输出: 2

注意:多维切片的每个内层切片是独立的,可拥有不同长度。

二、切片的拷贝与共享内存

  1. 浅拷贝(共享底层数组)
s1:=[]int{1,2,3}s2:=s1[0:2]// s2与s1共享底层数组s1[0]=100// 修改s1会影响s2fmt.Println(s2[0])// 输出: 100
  1. 深拷贝(独立内存)
    使用copy函数:
s1:=[]int{1,2,3}s2:=make([]int,len(s1))copy(s2,s1)// 复制元素到新切片s1[0]=100// 修改s1不影响s2fmt.Println(s2[0])// 输出: 1

三、切片作为函数参数

切片作为参数传递时,传递的是切片的值拷贝(即array、len、cap的副本),但由于array是指针,函数内可修改原切片的元素:

funcmodify(s[]int){s[0]=100// 修改底层数组的元素}funcmain(){s:=[]int{1,2,3}modify(s)fmt.Println(s[0])// 输出: 100}

若需在函数内扩容并影响原切片,需返回新切片:

funcappendElement(s[]int)[]int{returnappend(s,4)}s:=[]int{1,2,3}s=appendElement(s)// 需接收返回值以更新原切片

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询