跳转至

2026 年

Golang源码分析系列之Map底层实现

映射也被称为哈希表(hash table)、字典。它是一种由key-value组成的抽象数据结构。大多数情况下,它都能在O(1)的时间复杂度下实现增删改查功能。若在极端情况下出现所有key都发生哈希碰撞时则退回成链表形式,此时复杂度为O(N)。

映射底层一般都是由数组组成,该数组每个元素称为桶,它使用hash函数将key分配到不同桶中,若出现碰撞冲突时候,则采用链地址法(也称为拉链法)或者开放寻址法解决冲突。下图就是一个由姓名-号码构成的哈希表的结构图:

Go语言中映射中key若出现冲突碰撞时候,则采用链地址法解决,Go语言中映射具有以下特点:

  • 引用类型变量
  • 读写并发不安全
  • 遍历结果是随机的

数据结构

Go语言中映射的数据结构是runtime.hmap(runtime/map.go):

// A header for a Go map.
type hmap struct {
    count     int //  元素个数,用于len函数返回map元素数量
    flags     uint8 // 标志位,标志当前map正在写等状态
    B         uint8  // buckets个数的对数,即桶数量 = 2 ^ B
    noverflow uint16 // overflow桶数量的近似值,overflow桶即溢出桶,即链表法中存在链表上的桶的个数
    hash0     uint32 // 随机数种子,用于计算key的哈希值

    buckets    unsafe.Pointer // 指向buckets数组,如果元素个数为0时,该值为nil
    oldbuckets unsafe.Pointer // 扩容时指向旧的buckets
    nevacuate  uintptr        // 用于指示迁移进度,小于此值的桶已经迁移完成

    extra *mapextra // 额外记录overflow桶信息
}

pkg-config快速入门指南

pkg-config 是一个帮助开发人员在编译和链接程序时发现和使用库的辅助工具。它提供了一种方法来获取库的编译和链接参数,使得在编译时链接库变得更加容易和一致。pkg-config 通常用于Unix-like系统,并且支持多种编程语言。

pkg-config 的工作原理是查询一个名为.pc的文件,这些文件包含了关于库的元数据,例如库的安装位置、编译器标志、链接器标志等。当你安装一个库时,通常会在/usr/lib/pkgconfig/usr/share/pkgconfig目录下安装相应的.pc文件。

如何使用 pkg-config

查询库的编译和链接标志

使用pkg-config查询库的编译和链接标志是最常见的用途。例如,如果你想使用libopus库,你可以使用以下命令来获取编译和链接标志:

pkg-config --cflags --libs opus

这个命令会输出类似以下内容:

-I/usr/include/opus -lopus

这些标志可以直接在编译命令中使用。