当前位置:首页 > 文章列表 > Golang > Go问答 > Go roaring 原地集合运算与返回新位图有什么区别

Go roaring 原地集合运算与返回新位图有什么区别

来源:17golang原创 2026-10-31 08:55:45 0浏览 收藏

Go roaring 里最容易被忽略的差别,不是 And 和 Or 的集合含义,而是结果写到哪里:a.And(b)、a.Or(b) 会修改接收者 a;roaring.And(a, b)、roaring.Or(a, b) 则返回一个新的 *Bitmap,适合保留原输入。要不要“原地”,取决于这两个位图是不是还要被别的逻辑继续使用。

要点速览
  • 接收者方法把交集或并集写回当前 Bitmap,调用前要确认它可以被消耗。
  • 包级函数返回新的结果位图,适合保留输入、生成快照或把结果交给另一个模块。
  • 共享指针场景先考虑 Clone,回归检查至少比较原输入、结果集合和空集合行为。

先锁定两个 API 的修改边界

官方文档对方法的描述很直接:(*Bitmap).And 计算交集并把结果存入当前 Bitmap,(*Bitmap).Or 计算并集并把结果存入当前 Bitmap。也就是说,点号左边的变量就是被修改的对象。

包级函数的形态不同:roaring.And(x1, x2) 和 roaring.Or(x1, x2) 返回 *Bitmap。从调用约定上,应把它们当成“用两个输入得到一个结果”,不要把结果自动理解成第一个参数的别名。需要把原对象当作只读输入时,优先使用这种表达。

Go roaring 的 Bitmap A、Bitmap B、接收者方法和包级函数之间的输入与结果边界说明图
图1:Go roaring 两类集合运算 API 的边界说明图,不是运行截图或执行证据。

用最小示例对比 And 和 Or

下面把同一组输入分别交给两种写法。示例重点不是打印格式,而是观察变量在调用之后是否仍代表原集合。

package main

import (
    "fmt"

    "github.com/RoaringBitmap/roaring"
)

func main() {
    left := roaring.BitmapOf(1, 2, 3, 8)
    right := roaring.BitmapOf(2, 3, 5)

    // 接收者方法会把交集写回 left,调用后 left 只保留共同元素。
    inPlace := roaring.BitmapOf(1, 2, 3, 8)
    inPlace.And(right)
    fmt.Println("原地交集:", inPlace.ToArray())

    // 包级函数返回新的交集,left 和 right 仍可作为后续输入。
    intersection := roaring.And(left, right)
    fmt.Println("返回交集:", intersection.ToArray())
    fmt.Println("left 仍是:", left.ToArray())

    // Or 的选择规则相同:方法改接收者,包级函数留下输入并返回并集。
    union := roaring.Or(left, right)
    fmt.Println("返回并集:", union.ToArray())
}

在这个例子里,两种交集写法的集合内容可以相同,但对象生命周期不同:inPlace 被消耗成交集,left 仍然包含原始元素。并集也是同样的选择题;如果左侧位图代表缓存中的原始标签集合,直接调用 left.Or(right) 就会改变缓存语义。

处理共享指针与迁移风险

把原地方法从局部变量移到公共函数里,最容易出现“看起来只是优化,实际上改了调用方数据”的回归。Go 的 *Bitmap 传递的是对象指针:如果两个字段、缓存项或返回值指向同一个 Bitmap,那么对其中一个引用调用 And 或 Or,另一个引用看到的也是被修改后的内容。

需要原地算法的效率、但又不能改原对象时,先复制再修改:

func intersectForQuery(base, filter *roaring.Bitmap) *roaring.Bitmap {
    // 复制输入后再原地计算,避免改变调用方持有的 base。
    result := base.Clone()
    result.And(filter)
    return result
}

func mergeSnapshot(base, extra *roaring.Bitmap) *roaring.Bitmap {
    // 快照需要保留 base,所以把并集写入副本而不是共享对象。
    result := base.Clone()
    result.Or(extra)
    return result
}

如果没有明确的所有权协议,包级 roaring.And、roaring.Or 往往更容易读懂;如果已经约定“这个函数独占结果位图”,接收者方法可以减少一次中间对象表达。两者都不是绝对更快,选择应先服从对象所有权,再用基准测试比较。

Go roaring 共享指针、Clone、原地集合运算、结果观察与回归断言之间的所有权关系说明图
图2:围绕 Bitmap 所有权的迁移检查结构图,不是运行截图或监控结果。

建立回归检查和选择清单

迁移一段集合运算代码时,可以按下面的顺序检查,但不要把它误解成某个固定框架的测试模板:

问题适合的写法要观察的结果
左侧 Bitmap 可以被消费吗?left.And(right) 或 left.Or(right)调用后左侧就是交集或并集
两个输入之后还要复用吗?roaring.And(left, right) 或 roaring.Or(left, right)原输入保持可继续读取
需要统一返回一个新对象吗?base.Clone() 后调用方法修改集中在副本上
输入可能为空吗?先按业务决定空集语义,再检查 IsEmpty交集、并集的边界符合预期

测试时不要只断言最终结果。至少保留一份输入快照,在原地分支之后确认允许修改的对象发生了变化、禁止修改的对象没有变化;如果代码会在多个 goroutine 间共享 Bitmap,还要遵守库文档给出的同步要求,不能把“返回新位图”误当成对同一输入对象并发读写的通用保护。

常见问题

原地 And 和 roaring.And 的集合结果一定不同吗?

不一定。对相同输入,它们都可以得到交集;关键差异是结果写入当前对象还是返回新位图。

为了避免修改输入,是否必须先 Clone?

不一定。可以直接使用包级函数;如果业务更适合接收者方法,再先对需要保留的输入调用 Clone。

Or 也遵循同一条规则吗?

是。(*Bitmap).Or 把并集写回当前 Bitmap,roaring.Or 返回并集结果;迁移时检查的是对象所有权,而不是只看运算符名字。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Redis ZREMRANGEBYLEX 怎样删除同分数成员的字典区间Redis ZREMRANGEBYLEX 怎样删除同分数成员的字典区间
上一篇
Redis ZREMRANGEBYLEX 怎样删除同分数成员的字典区间
Go roaring Rank与Select分别解决什么查询
下一篇
Go roaring Rank与Select分别解决什么查询
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    808次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    798次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    888次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    860次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    686次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码