chiachan
chiachan
Published on 2025-01-06 / 14 Visits
0

go语言学习笔记 - 数组与切片

#go

go语言学习笔记 - 数组与切片

数组(Array)是定长的值类型。是一段连续的内容
切片(Slice)是动态的引用类型。是一个结构体

数组(Array)

var arr [3]int = [3]int{1, 2, 3}

特点:

  • 固定长度​:[3]int 是一个长度为 3 的数组类型。
  • 值类型​:传参/赋值时会 ​拷贝整个数组​(不共用内存)。
  • 类型包含长度​:[3]int[4]int 是完全不同的类型。

切片(Slice)

var s []int = []int{1, 2, 3}

特点:

  • 动态长度​:可以增删扩容。
  • 引用类型​:底层指向数组,传参时只是​复制了引用结构​(共用内存)。
  • 包含结构​:切片底层是一个结构体:

扩容机制

Go 切片扩容规则(简化理解):

  • 小于 1024:通常 每次扩容容量 ×2
  • 大于 1024:每次大约按 1.25 倍增长
  • 扩容时会 ​新建更大的底层数组并拷贝内容​(旧数组可能变为垃圾,等待 GC)
s := make([]int, 0)
for i := 0; i < 10; i++ {
	s = append(s, i)
	fmt.Printf("len=%d cap=%d\n", len(s), cap(s))
}

底层结构

type slice struct {
    ptr unsafe.Pointer // 指向底层数组的指针
    len int            // 当前切片长度
    cap int            // 容量(cap 可增长)
}

常见坑点

  1. 切片截取仍引用原数组​,容易出现数据共享问题:
b := a[:3]
b[0] = 999
fmt.Println(a) // [999 2 3 4 5]
  1. append 后不一定是同一个数组​(因为可能触发了扩容)
    小技巧:避免在共享切片上直接 append;并发读写时加锁
a := []int{1, 2, 3}
b := append(a, 4)
b[0] = 100
fmt.Println(a) // [1 2 3],a 没变,因为 append 触发了扩容