Go语言第五章(数组和切片)

数组和切片

数组和切片都是用来存放一组同类型数据的结构,写法也很像,所以放在一起讲。先记住一个关键区别:数组长度固定,切片长度可变

数组

数组的长度在声明时就定死了,之后不能改。元素类型随意,但同一数组里必须是同一种类型。

语法:

go 复制代码
var 数组名 = [长度]类型{值1, 值2, 值3, ...}
数组名 := [长度]类型{值1, 值2, 值3, ...}

例子:

go 复制代码
package main

import "fmt"

func main() {
	var arr = [5]int{1, 2, 3, 4, 5}
	arr2 := [5]int{6, 7, 8, 9, 10}
	fmt.Println(arr, arr2)
}

两种写法都能声明数组:var 完整声明,或 := 短声明。[5]int 表示「长度为 5、元素类型为 int」------长度是类型的一部分[5]int[4]int 是两种不同类型。

读写元素

通过下标访问和修改元素。下标从 0 开始:

go 复制代码
package main

import "fmt"

func main() {
	arr := [4]string{"唱", "跳", "rap", "篮球"}
	// 下标:  0    1     2      3

	fmt.Println(arr[0]) // 唱

	arr[0] = "篮球"
	fmt.Println(arr[0]) // 篮球
}

获取长度

用内置函数 len 获取数组长度:

go 复制代码
package main

import "fmt"

func main() {
	arr := [4]string{"唱", "跳", "rap", "篮球"}
	fmt.Println(len(arr)) // 4
}

切片

切片可以看作「可变长度的数组」。日常开发里用得比数组多得多。

语法上,把数组的长度去掉就行:

go 复制代码
var 切片名 = []类型{值1, 值2, 值3, ...}
切片名 := []类型{值1, 值2, 值3, ...}

例子:

go 复制代码
package main

import "fmt"

func main() {
	var s1 = []int{1, 2, 3}
	s2 := []string{"唱", "跳", "rap"}
	fmt.Println(s1, s2)
}

[]int 没有写死长度,所以这是切片,不是数组。

读写元素

读写方式和数组一样,也是按下标操作:

go 复制代码
package main

import "fmt"

func main() {
	s := []string{"唱", "跳", "rap", "篮球"}

	fmt.Println(s[1]) // 跳

	s[1] = "打球"
	fmt.Println(s) // [唱 打球 rap 篮球]
}

长度与容量

切片有两个常用属性:

  • len:当前元素个数
  • cap:底层数组的容量(还能装多少,不用立刻扩容)
go 复制代码
package main

import "fmt"

func main() {
	s := []int{1, 2, 3}
	fmt.Println(len(s)) // 3
	fmt.Println(cap(s)) // 3
}

切片截取

切片[低:高] 可以从已有切片(或数组)上「切」出一段,得到一个新切片。区间是左闭右开 :包含下标 ,不包含下标

go 复制代码
package main

import "fmt"

func main() {
	s := []int{10, 20, 30, 40, 50}
	// 下标:  0   1   2   3   4

	fmt.Println(s[1:4]) // [20 30 40]  取下标 1、2、3
	fmt.Println(s[:3])  // [10 20 30]  从头切到下标 3(不含 3)
	fmt.Println(s[2:])  // [30 40 50]  从下标 2 切到末尾
	fmt.Println(s[:])   // [10 20 30 40 50]  整段复制一份切片头
}

几种常见写法:

写法 含义
s[低:高] (不含
s[:高] 从开头到 (不含
s[低:] 到末尾
s[:] 整段截取

也可以对数组做同样的事,结果是一个切片:

go 复制代码
package main

import "fmt"

func main() {
	arr := [5]int{10, 20, 30, 40, 50}
	s := arr[1:4]
	fmt.Println(s) // [20 30 40]
}

截取出来的切片和原数据共享底层数组:改一边,另一边也会变。后面做前置追加、中间插入时,会经常用到 s[:idx]s[idx:] 这种写法。

追加元素

切片长度可变,最常见的操作就是往里面加元素。Go 只内置了往尾部 追加的 append;往前面插、往中间插,都要靠 append 和切片截取自己拼。

尾部追加

append 接收原切片和要追加的元素,返回一个新切片。容量不够时会自动扩容:

go 复制代码
package main

import "fmt"

func main() {
	s := []int{1, 2, 3}
	s = append(s, 4, 5)
	fmt.Println(s) // [1 2 3 4 5]
}

一次可以追加多个值。记得把返回值接回来(s = append(...)),否则原切片看不到新增内容。

前置追加

Go 没有「往头部插入」的内置函数,思路是:先建一个装着新元素的切片,再用 append 把原切片接在后面。

这里会用到 ...(展开操作符):s... 表示把切片 s 里的元素一个个拆开,当作多个参数传给 append

go 复制代码
package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5}
	s = append([]int{-1, 0}, s...)
	// 等同于:append([]int{-1, 0}, 1, 2, 3, 4, 5)
	fmt.Println(s) // [-1 0 1 2 3 4 5]
}

拆开看就两步:

  1. []int{-1, 0}:要插到前面的新元素
  2. s...:把原来的 1, 2, 3, 4, 5 展开,接到后面
中间插入

中间插入同样没有内置方法,本质是把切片拆成「前半段 + 新元素 + 后半段」,再拼回去。

假设切片是 [-1 0 1 2 3 4 5],想在 2 后面(下标 4 的位置)插入 100, 200

go 复制代码
package main

import "fmt"

func main() {
	s := []int{-1, 0, 1, 2, 3, 4, 5}
	// 下标:  0  1  2  3  4  5  6
	idx := 4 // 从下标 4 开始插入,也就是 2 的后面

	s = append(s[:idx], append([]int{100, 200}, s[idx:]...)...)
	fmt.Println(s) // [-1 0 1 2 100 200 3 4 5]
}

这行可以拆成三块理解:

部分 含义 结果
s[:idx] 插入点之前 [-1 0 1 2]
[]int{100, 200} 要插入的内容 [100 200]
s[idx:] 插入点及之后 [3 4 5]

先用 append([]int{100, 200}, s[idx:]...) 得到 [100 200 3 4 5],再接到 s[:idx] 后面,就拼成了最终结果。

写法有点绕,但记口诀就行:前半段 + 新元素 + 后半段

数组 vs 切片

数组 切片
长度 固定,声明时确定 可变,可用 append 增减
类型写法 [5]int []int
传递方式 值拷贝(复制整个数组) 引用底层数组(更轻量)
使用场景 长度已知且不变 日常开发更常用

入门阶段可以先记住:不确定长度、或需要增删,就用切片。

作业

  1. 数组基础 :声明一个长度为 5int 数组,依次赋值为 15,打印第 3 个元素(注意下标),再用 len 打印数组长度。
  2. 切片声明与追加 :声明切片 []string{"唱", "跳", "rap"},用 append 在尾部追加 "篮球",打印切片内容、lencap
  3. 切片截取 :给定 s := []int{10, 20, 30, 40, 50},分别打印 s[1:4]s[:3]s[2:]s[:],对照文中表格核对结果。
  4. 前置与中间插入 :以 []int{1, 2, 3, 4, 5} 为起点,先把 -1, 0 插到最前面;再在元素 3 后面插入 100, 200,最终打印完整切片。
  5. 综合练习 :用切片存储若干门课程分数(如 []int{95, 58, 76, 42, 88})。遍历切片:低于 60 的改为 0(表示重考),然后截取前 3 门课的分数打印,并统计及格科目数量。
相关推荐
武子康3 分钟前
我让 Qwen3.6-27B 真改了一次 Git 仓库:工具调用怎样形成 Agent 闭环
人工智能·后端·agent
云浪10 分钟前
如何让大模型操作 MySQL 数据库?
javascript·人工智能·后端
SamChan9011 分钟前
PDF 翻译服务的全链路可观测性设计:OpenTelemetry + Jaeger + Loki 实战方案
后端·python·pdf·机器翻译
我的xiaodoujiao14 分钟前
Django 基础知识详细图文教程 1-Django 介绍
后端·python·学习·测试工具·django
IT毕设实战小研34 分钟前
基于大数据的二手车数据分析与预测
java·大数据·后端·爬虫·python·算法·课程设计
覆东流9 小时前
7.Java数组
java·开发语言·后端
threerocks10 小时前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
JavaPub-rodert10 小时前
王仕宇在 Go Context 如何解决协程泄漏与超时控制
开发语言·后端·golang·iphone·javapub·王仕宇
深漂的华哥10 小时前
Ruoyi-Plus前后端分离场景下,数据加密传输
java·spring boot·后端·开源·maven·ruoyi
why技术12 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端