Skip to content

数据结构

Go 语言虽然语法简洁,但内置了多种功能强大的核心数据结构。这些数据结构是 Go 程序的基础构建块,深入理解它们的实现原理,有助于编写更高效的代码。本文将介绍 Go 中最常用的几种数据结构及其底层实现。

基础数据结构

slice 切片

切片是 Go 语言中最常用的数据结构,是对数组的抽象和封装。主要特点:

  • 动态大小:切片的长度可以动态增长
  • 引用语义:切片传递时只复制结构体,不复制底层数组
  • 扩容机制:当容量不足时会自动扩容

切片在运行时由 slice 结构体表示,包含指向底层数组的指针、长度和容量三个字段。

string 字符串

字符串是 Go 中最基础的数据类型之一,主要特点:

  • 不可变性:字符串一旦创建就不能修改
  • UTF-8 编码:通常表示 UTF-8 编码的文本
  • 零值安全:字符串的零值是空字符串 "",而非 nil

字符串在运行时由 stringStruct 结构体表示,包含指向字节数组的指针和长度。

容器数据结构

map 映射表

map 是 Go 语言内置的键值对容器,底层采用哈希表实现。主要特点:

  • 哈希表实现:通过哈希函数快速定位元素
  • 自动扩容:当负载因子过高时自动进行扩容
  • 非并发安全:并发读写需要额外的同步机制

map 在运行时由 hmap 结构体表示,包含桶数组、哈希种子、元素计数等字段。

syncmap 并发映射

sync.Map 是标准库提供的并发安全映射,适用于读多写少的场景。主要特点:

  • 读写分离:使用 read 和 dirty 两个 map 实现读写分离
  • 原子操作:read map 使用原子操作,无需加锁
  • 渐进迁移:miss 计数达到阈值时将 dirty 提升为 read

sync.Map 通过空间换时间的方式,在特定场景下提供了比 map + mutex 更好的性能。

并发数据结构

channel 通道

channel 是 Go 语言贯彻 CSP 思想的典型代表,用于协程间通信。主要特点:

  • 协程通信:通过 channel 实现协程间的数据传递
  • 同步机制:无缓冲 channel 可用于协程同步
  • 有锁队列:底层是带锁的环形队列

channel 在运行时由 hchan 结构体表示,包含环形缓冲区、等待队列等字段。

select 多路复用

select 可以同时监听多个 channel 的状态,实现多路复用。主要特点:

  • 非阻塞:可以非阻塞地检查多个 channel 是否可用
  • 随机选择:多个 channel 同时可用时随机选择一个执行
  • 超时控制:配合 time.After 实现超时机制

select 在运行时由 scase 结构体表示每个分支,通过轮询机制检查 channel 状态。

学习建议

建议按照以下顺序学习:

  1. 先学习 slice 切片string 字符串,理解基础数据结构
  2. 再学习 map 映射表,了解哈希表的实现
  3. 然后学习 channel 通道,理解协程通信机制
  4. 接着学习 select 多路复用,掌握多路复用技巧
  5. 最后学习 syncmap 并发映射,了解并发安全的实现方式