应选用 github.com/google/uuid,它是当前唯一被 google 官方维护、ci 持续验证、支持 rfc 4122 全版本(v1/v3/v4/v5)的生产级实现,api 稳定且无隐藏依赖。

go.uuid 选哪个包?google/uuid 是当前唯一可选的生产级实现
别再用 github.com/satori/go.uuid——它已停更,Go 1.16+ 下 go get 失败,且底层用 math/rand 不满足支付类场景审计要求。目前唯一被 Google 官方维护、CI 持续验证、社区广泛使用的只有 github.com/google/uuid。
它支持全部 RFC 4122 版本(v1/v3/v4/v5),API 稳定,无隐藏依赖。注意:它不内置 v6/v7/v8,这些新版 UUID 需要额外库或手写逻辑。
- 安装命令固定为:
go get github.com/google/uuid - 导入后直接用
uuid.New(),等价于uuid.NewV4(),生成标准 v4 随机 UUID - 不要 import
uuid包名冲突:确保别同时引入其他 uuid 库,否则编译报错ambiguous selector
高并发下 UUID 生成变慢?问题不在算法,在随机源
uuid.NewUUID() 在容器或压测时 P99 延迟跳到 10ms+,不是代码写得差,而是它强制调用 crypto/rand.Read() 读取 /dev/urandom —— 这个熵源在低熵环境(如 CI、K8s initContainer)会短暂阻塞。
99% 的业务 ID 场景(用户 ID、traceID、订单前缀)根本不需要密码学强度随机性,只需全局唯一 + 高吞吐。这时候应该切到 uuid.NewRandom():
-
uuid.Must(uuid.NewRandom())是安全快捷写法:它用math/rand+ 时间戳 + PID 混合种子,不碰系统熵池,实测快 3 倍(35ns vs 120ns) - 生成格式完全一致(
8-4-4-4-12hex 字符串),下游解析、数据库存储、HTTP 传输全兼容 - 错误只在初始化失败时返回(基本不会发生),所以
Must是合理选择
v4 不够用?时间有序需求必须换 v7 或 snowflake
如果你的主键要进 MySQL,且期望 ORDER BY id 有业务意义(比如查最近 10 条订单),纯 v4 UUID 就是反模式:二进制无序,B-tree 插入引发页分裂,索引效率下降 20%+;JS 端还可能因 Number.MAX_SAFE_INTEGER 截断出错。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
此时有两个务实选择:
-
v7 UUID:时间戳前置(精度 100ns),保留标准格式,兼容现有 schema。可用
github.com/oklog/ulid或手写(用time.Now().UnixNano() / 100+ 6 字节随机填充) -
sonyflake:比 bwmarrin/snowflake 更稳——强制你提供
MachineIDFunc,避免容器重启撞号;必须设StartTime(推荐服务上线前 1 小时),否则高位全 0 影响索引
别信“v4 每秒百万不重复”——那是概率,不是工程保证;ID 是主键、分片键、trace 关联字段,不能靠赌。
批量生成 UUID 时 goroutine 竞争?别自己 new rand.Rand
有人想提速就写 rand.New(rand.NewSource(time.Now().UnixNano())),结果性能反而更差:它触发 rand.globalRand 全局锁,多 goroutine 下锁争抢严重。
正确做法是复用无锁实例:
-
uuid.NewRandom()内部已做线程安全封装,直接并发调用即可 - 若需更高吞吐(比如每秒 10w+),用
github.com/rs/xid:它内置无锁随机器,带毫秒级时间前缀,字符串长度更短(20 字符),且天然有序 - 自建方案慎用
crypto/rand:仅当生成 API 密钥、nonce、临时 token 等安全敏感 ID 时才需要
真正容易被忽略的是节点 ID 注入方式——在 K8s 环境下,MAC 地址常为 00:00:00:00:00:00,v1 和 sonyflake 都会退化成纯时间戳,必须从 HOSTNAME+POD_NAME 哈希或 Etcd 拉取注册 ID。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










