# 总结了 7 种 Go 语言生成唯一ID的实用方法,立即收藏,随时备用!
在现代分布式系统中,生成唯一 ID 是一个非常重要的环节,尤其在高并发、跨服务的场景下。
Go 语言中,有很多开源包和方法可以用来生成唯一 ID。
今天咱们就来深入探讨几种常见的生成唯一 ID 的方式,详细列举它们的特性、优点、缺点,以及适用场景。
## 1. 使用 google/uuid 包
**什么是 UUID?**
UUID(Universally Unique Identifier)是 128 位长的 ID,通常以 36 个字符的格式展示,如 "550e8400-e29b-41d4-a716-446655440000"。
**示例代码:**
```go
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String()) // 输出类似 "550e8400-e29b-41d4-a716-446655440000"
}
特性:
- 唯一性:基于随机数和时间戳组合。
- 无序性:不具备时间排序性。
- 性能:生成速度较快。
优点:
- 适合分布式系统生成全局唯一 ID。
- 无需中央节点,使用简单。
缺点:
- 长度较长,不适合展示在 UI 上。
- 不具备时间排序特性。
适用场景:
分布式环境中的全局唯一 ID 生成,如用户 ID、订单 ID 等。
2. 使用 bwmarrin/snowflake 包
什么是雪花算法?
雪花算法生成 64 位整型 ID,分为 1 位符号位、41 位时间戳、10 位机器 ID 和 12 位序列号。
示例代码:
package main
import (
"fmt"
"github.com/bwmarrin/snowflake"
)
func main() {
node, _ := snowflake.NewNode(1)
id := node.Generate()
fmt.Println(id) // 输出类似 "1234567890123456789"
fmt.Println(id.Int64()) // 获取 int64 类型的 ID
}
特性:
- 唯一性:时间戳、机器 ID 和序列号组合。
- 排序性:具备时间排序特性。
- 性能:生成速度快。
优点:
- ID 紧凑,适合数据库主键或分布式系统。
- 有序性便于插入数据库。
缺点:
- 需要配置机器节点 ID,部署稍复杂。
适用场景:
分布式系统中需要有序的唯一 ID,如订单号、用户 ID 等。
3. 使用 oklog/ulid 包
什么是 ULID?
ULID 是一种可排序的唯一 ID,比 UUID 更具可读性和排序性。
示例代码:
package main
import (
"fmt"
"github.com/oklog/ulid/v2"
"math/rand"
"time"
)
func main() {
entropy := ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0)
id := ulid.MustNew(ulid.Timestamp(time.Now()), entropy)
fmt.Println(id.String()) // 输出类似 "01FHZB1E8B9B8YZW6CVDBKMT6T"
}
特性:
- 唯一性:时间戳与随机数组合。
- 排序性:具备时间排序。
- 可读性:26 个字符,较 UUID 更紧凑。
优点:
- 有序性,便于数据库插入和日志记录。
- 紧凑且易读。
缺点:
- 高并发下有碰撞风险。
适用场景:
消息队列、日志 ID 等需要排序且唯一的场景。
4. 使用 teris-io/shortid 包
什么是短 ID?
shortid 生成简短唯一的 ID,适用于短链或验证码等场景。
示例代码:
package main
import (
"fmt"
"github.com/teris-io/shortid"
)
func main() {
id, _ := shortid.Generate()
fmt.Println(id) // 输出类似 "dppUrjK3"
}
特性:
- 唯一性:基于随机数生成。
- 无序性:不具备时间排序。
- 可读性:短 ID,便于展示。
优点:
- 适合 UI 和用户交互场景。
- 生成简便,不依赖中央节点。
缺点:
- 不具备排序特性。
适用场景:
短链接、验证码、临时文件名等。
5. 使用 rs/xid 包
什么是 XID?
xid 是轻量级的唯一 ID,20 个字符,包含时间戳、机器 ID 和计数器。
示例代码:
package main
import (
"fmt"
"github.com/rs/xid"
)
func main() {
id := xid.New()
fmt.Println(id.String()) // 输出类似 "9m4e2mr0ui3e8a215n4g"
}
特性:
- 唯一性:通过时间戳、机器 ID 和计数器组合。
- 排序性:具备时间排序性。
- 性能:生成速度快。
适用场景:
分布式数据库主键、消息队列等。
6. 使用 segmentio/ksuid 包
什么是 KSUID?
ksuid 是可排序的唯一 ID,27 字符 Base62 编码,包含时间戳。
示例代码:
package main
import (
"fmt"
"github.com/segmentio/ksuid"
)
func main() {
id := ksuid.New()
fmt.Println(id.String()) // 输出类似 "1CHzCEl82ZZe2r2KS1qEz3XF8Ve"
}
特性:
- 唯一性:基于时间戳和随机数生成。
- 排序性:具备时间排序。
- 可读性:27 字符,适合日志记录。
适用场景:
日志、消息队列等需要唯一且具备时间排序的场景。
7. 使用 sony/sonyflake 包
什么是 Sonyflake?
Sonyflake 生成高效的 64 位唯一 ID,由时间戳、机器 ID 和序列号组成。
示例代码:
package main
import (
"fmt"
"github.com/sony/sonyflake"
)
func main() {
sf := sonyflake.NewSonyflake(sonyflake.Settings{})
id, _ := sf.NextID()
fmt.Println(id) // 输出类似 "173301874793540608"
}
特性:
- 唯一性:时间戳、机器 ID 和序列号组合。
- 排序性:具备时间排序。
- 可扩展性:支持自定义机器 ID 和时间戳精度。
适用场景:
高性能分布式系统,如订单号、日志序列等。
总结
方法 | 特性 | 有序性 | 长度 | 适用场景 |
---|---|---|---|---|
UUID | 全局唯一 | 无序 | 长(36) | 分布式系统标识符 |
Snowflake | 全局唯一、排序 | 有序 | 中(64位) | 高性能分布式系统 |
ULID | 全局唯一、可排序 | 有序 | 中(26) | 日志、消息队列 |
XID | 全局唯一、时间排序 | 有序 | 中(20) | 分布式数据库主键 |
KSUID | 全局唯一、时间排序 | 有序 | 中(27) | 日志、消息队列 |
ShortID | 简短唯一 | 无序 | 短(7-14) | 短链接、验证码 |
Sonyflake | 高性能、全局唯一、排序 | 有序 | 中(64位) | 高性能分布式系统 |
根据业务需求、系统架构和性能要求选择合适的 ID 生成策略,确保系统稳定和高效。