Go语言中三种容器类型的数据结构

  • Louis
  • 发布于 21小时前
  • 阅读 112

在Go语言中,有三种主要的容器类型用于存储和操作集合数据:数组(Array)、切片(Slice)和映射(Map)。

基本概念

在 Go 语言中,有三种主要的容器类型用于存储和操作集合数据:数组(Array)切片(Slice)映射(Map)。以下是它们的详细说明和对比:

1. 数组(Array)

定义
数组是具有 固定长度 的容器,存储相同类型的元素。长度在声明时确定,不可变。

特点

  • 值类型:赋值或传参时会复制整个数组。
  • 内存连续分配,访问速度快。

声明与初始化

// 声明长度为3的整型数组,默认初始化为零值
var arr1 [3]int

// 声明并初始化
arr2 := [3]int{1, 2, 3}

// 自动推断长度
arr3 := [...]int{4, 5, 6}

使用场景
适合需要固定大小且对内存敏感的场合(如底层算法优化),但日常开发中较少直接使用。

2. 切片(Slice)

定义
切片是基于数组的 动态长度 抽象,提供更灵活的容器。切片本身是引用类型,底层指向一个数组。

特点

  • 动态扩容:长度可动态增长(通过 append 函数)。
  • 引用语义:赋值或传参时传递指针,多个切片可能共享底层数组。

声明与初始化

// 直接声明切片(nil切片)
var s1 []int

// 通过数组创建切片
arr := [5]int{1, 2, 3, 4, 5}
s2 := arr[1:3] // 包含元素 [2, 3]

// 使用 make 创建切片
s3 := make([]int, 3, 5) // 长度3,容量5

// 直接初始化
s4 := []int{1, 2, 3}

常用操作

  s := []int{1, 2}
  s = append(s, 3)      // 追加元素 → [1, 2, 3]
  sub := s[1:]          // 截取子切片 → [2, 3]

使用场景
绝大多数集合操作的默认选择(如动态列表、数据流处理)。

3. 映射(Map)

定义
映射是 键值对(Key-Value) 的无序集合,通过哈希表实现,键必须可哈希(如 intstring)。

特点

  • 动态扩容:自动增长以容纳更多键值对。
  • 引用语义:赋值或传参时传递指针。
  • 键唯一,值可重复。

声明与初始化

  // 声明一个映射(nil映射,不可直接使用)
  var m1 map[string]int

  // 使用 make 初始化
  m2 := make(map[string]int)

  // 直接初始化
  m3 := map[string]int{
      "Alice": 25,
      "Bob":   30,
  }

常用操作

  m := map[string]int{}
  m["Charlie"] = 28    // 添加或修改键值对
  age, ok := m["Bob"]  // 检查键是否存在(ok为bool)
  delete(m, "Alice")   // 删除键

使用场景
快速查找、去重计数、配置管理等需要键值关联的场景。

对比总结

特性 数组(Array) 切片(Slice) 映射(Map)
长度 固定 动态可变 动态可变
类型语义 值类型(复制整个数据) 引用类型(共享底层数组) 引用类型(共享存储)
内存分配 编译时确定 运行时动态分配 运行时动态分配
访问方式 索引(0-based) 索引(0-based) 键(Key)
主要用途 固定大小数据块 动态集合操作 键值对关联存储

注意事项

  1. 切片共享底层数组
    多个切片可能共享同一底层数组,修改一个切片可能影响其他切片。

    arr := [3]int{1, 2, 3}
    s1 := arr[:]  // s1 = [1,2,3]
    s2 := s1[1:]  // s2 = [2,3]
    s2[0] = 100   // s1变为 [1,100,3]
  2. 映射的无序性
    遍历映射时,键值对的顺序不固定(Go 1.12+ 在扩容时随机化遍历顺序)。

  3. 并发安全
    切片和映射在并发读写时需加锁(或使用 sync.Map)。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Louis
Louis
web3 developer,技术交流或者有工作机会可加VX: magicalLouis