Skip to content

数组和切片

数组

数组是固定长度的同类型元素序列。

数组声明

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]
}