数组和切片
数组
数组是固定长度的同类型元素序列。
数组声明
go
// 声明数组(零值)
var arr [5]int
// 初始化数组
nums := [5]int{1, 2, 3, 4, 5}
// 自动计算长度
autoLen := [...]int{1, 2, 3, 4, 5} // 长度为5
// 指定索引初始化
specified := [5]int{1: 10, 3: 30} // [0, 10, 0, 30, 0]数组操作
go
nums := [5]int{1, 2, 3, 4, 5}
// 访问元素
fmt.Println(nums[0]) // 1
fmt.Println(nums[4]) // 5
// 修改元素
nums[0] = 100
// 获取长度
fmt.Println(len(nums)) // 5
// 遍历数组
for i := 0; i < len(nums); i++ {
fmt.Println(nums[i])
}
// 使用range遍历
for index, value := range nums {
fmt.Printf("索引: %d, 值: %d\n", index, value)
}多维数组
go
// 声明二维数组
var matrix [3][3]int
// 初始化二维数组
matrix = [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
// 遍历二维数组
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%d ", matrix[i][j])
}
fmt.Println()
}切片
切片是动态长度的、灵活的数组视图。
创建切片
go
// 使用make创建
slice1 := make([]int, 5) // 长度5,容量5
slice2 := make([]int, 5, 10) // 长度5,容量10
// 切片字面量
slice3 := []int{1, 2, 3, 4, 5}
// 从数组创建切片
arr := [5]int{1, 2, 3, 4, 5}
slice4 := arr[1:4] // [2, 3, 4]
slice5 := arr[:3] // [1, 2, 3]
slice6 := arr[2:] // [3, 4, 5]
slice7 := arr[:] // [1, 2, 3, 4, 5]切片属性
go
slice := make([]int, 3, 10)
fmt.Println(len(slice)) // 长度: 3
fmt.Println(cap(slice)) // 容量: 10切片操作
go
package main
import "fmt"
func main() {
// 创建切片
numbers := []int{1, 2, 3, 4, 5}
fmt.Println("原始切片:", numbers)
// 添加元素
numbers = append(numbers, 6)
fmt.Println("添加6后:", numbers)
// 添加多个元素
numbers = append(numbers, 7, 8, 9)
fmt.Println("添加7,8,9后:", numbers)
// 添加另一个切片
more := []int{10, 11}
numbers = append(numbers, more...)
fmt.Println("添加切片后:", numbers)
// 截取切片
subSlice := numbers[1:4]
fmt.Println("截取[1:4]:", subSlice)
// 遍历切片
for i, v := range numbers {
fmt.Printf("索引%d: 值%d\n", i, v)
}
}copy函数
go
src := []int{1, 2, 3}
dst := make([]int, len(src))
// 复制切片
copied := copy(dst, src)
fmt.Println(copied) // 3
fmt.Println(dst) // [1 2 3]删除元素
go
// 删除索引i的元素
func remove(slice []int, i int) []int {
return append(slice[:i], slice[i+1:]...)
}
func main() {
nums := []int{1, 2, 3, 4, 5}
nums = remove(nums, 2) // 删除索引2的元素
fmt.Println(nums) // [1 2 4 5]
}切片扩容原理
当切片容量不足时,append 会自动扩容:
go
func main() {
s := make([]int, 0, 1)
for i := 0; i < 10; i++ {
fmt.Printf("len=%d, cap=%d\n", len(s), cap(s))
s = append(s, i)
}
}
// 输出: 容量按 1, 2, 4, 8, 16... 增长数组 vs 切片
| 特性 | 数组 | 切片 |
|---|---|---|
| 长度 | 固定 | 动态 |
| 传递方式 | 值传递 | 引用传递 |
| 声明 | [n]T | []T |
| 比较 | 可比较 | 不可比较(只能与nil比较) |
实用技巧
切片去重
go
func unique(slice []int) []int {
keys := make(map[int]bool)
result := []int{}
for _, v := range slice {
if !keys[v] {
keys[v] = true
result = append(result, v)
}
}
return result
}切片反转
go
func reverse(slice []int) []int {
for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
slice[i], slice[j] = slice[j], slice[i]
}
return slice
}切片过滤
go
func filter(slice []int, fn func(int) bool) []int {
result := []int{}
for _, v := range slice {
if fn(v) {
result = append(result, v)
}
}
return result
}
func main() {
nums := []int{1, 2, 3, 4, 5, 6}
evens := filter(nums, func(n int) bool {
return n%2 == 0
})
fmt.Println(evens) // [2 4 6]
}