问题的背景:
Go 默认没有集合结构,但经常会遇到处理唯一元素的需求。最佳结构是 map[string]struct{},其中键是元素,空结构用作“存在标记”。这是进行快速成员测试的常见模式。
问题:
内置集合的缺乏使得新手觉得正确实现唯一集合很复杂。同时还需要理解为什么 struct{} 在值方面比 bool 或 int 更有效。
解决方案:
在 Go 中实现集合使用 map[string]struct{}。空结构 struct{} 不需要内存(零大小),而 map 提供快速访问。示例:
set := make(map[string]struct{}) set["foo"] = struct{}{} if _, ok := set["foo"]; ok { fmt.Println("存在") } delete(set, "foo")
关键特点:
为什么不能使用 slice/数组作为值?
slice/数组作为集合不提供常数时间的元素查找 — 必须遍历所有值,这样会很慢。
map[string]struct{} 和 map[string]bool 有什么区别?
map[string]bool 占用更多内存:每个键存储一个 bool,而 struct{} 是空类型,不分配任何东西。
set := map[string]bool{"foo": true}
可以使用 int 代替 struct{} 吗?
可以,但 int 总是占用内存。struct{} 更通用:如果只需要“标记”(存在的角色),它更好。
set := map[string]int{"foo": 1} // 但存储的是(键 -> 数字)
由于不知道,分配了 map[string]bool 作为唯一 IP 地址的集合。结果,数百万地址时内存消耗比 struct{} 增加了一倍。
优点:
缺点:
在项目中使用 map[string]struct{} 来存储唯一的电子邮件。负载减少,速度更快,几乎不占用值的内存。
优点:
缺点: