Go标准库不支持mmap,必须用第三方库如github.com/edsrzf/mmap-go;它跨平台、自动处理页对齐与错误映射,只读用mmap.RDONLY,读写需mmap.RDWR加mm.Flush()持久化。

Go 中 mmap 读写需要第三方库,标准库不支持
Go 标准库 os 和 io 包不提供内存映射(mmap)接口。想用 mmap,必须借助 golang.org/x/sys/unix(Linux/macOS)或 golang.org/x/sys/windows(Windows),或者更推荐的封装库——github.com/edsrzf/mmap-go。后者跨平台、API 简洁,且处理了信号、页面对齐、同步等底层细节。
用 mmap-go 实现只读映射最安全
多数场景只需读取大文件(如日志分析、二进制解析),此时应优先用只读映射,避免意外写入或权限问题。
-
mm, err := mmap.Open("data.bin", mmap.RDONLY)—— 打开只读映射,失败时返回syscall.EACCES或syscall.ENOENT - 映射后直接访问
mm的字节切片:mm[1024:2048],无需额外read()调用 - 用完必须调用
mm.Unmap(),否则资源泄漏(尤其在 long-running 服务中) - 注意:映射区域长度固定为文件当前大小,文件后续增长不会自动反映到
mm中
写入 mmap 需要显式设置标志并小心同步
写入映射内容不是“改完就落地”,必须控制写入时机和持久化行为,否则数据可能丢失。
- 创建时加
mmap.RDWR标志:mm, err := mmap.Open("data.bin", mmap.RDWR) - 修改
mm切片后,调用mm.Flush()将脏页写回磁盘(等价于msync(MS_SYNC)) - 若只希望写入部分区域,可传偏移和长度:
mm.FlushAt(4096, 8192) - 不调用
Flush()就退出程序?数据大概率丢失——内核可能延迟回写,且进程崩溃时未刷出页会丢弃
常见错误:文件打开模式与 mmap 标志不匹配
这是 runtime panic 或 invalid argument 错误的高发原因。
立即学习“go语言免费学习笔记(深入)”;
- 用
os.OpenFile(..., os.O_RDONLY, 0)打开文件,却传mmap.RDWR给mmap.Open()→ 失败(Linux 返回EINVAL) - 文件以
os.O_CREATE打开但未写入任何数据,直接 mmap → 映射长度为 0,访问mm[0]panic - Windows 下路径含中文或特殊字符时,确保传入的是 UTF-16 编码的
syscall.StringToUTF16Ptr(),mmap-go已封装,但自建 syscall 调用容易漏掉
真正麻烦的不是怎么映射,而是判断什么时候该 flush、什么时候该 unmap、以及是否真的需要 mmap——小文件用 os.ReadFile 更快更稳;只有 GB 级别、随机访问密集、且需零拷贝的场景,才值得引入 mmap 复杂度。


















