Grafana Tempo 中的 go-humanize 工具库:让字节、时间与数字输出更人性化
Grafana Tempo 中的 go-humanize 工具库让字节、时间与数字输出更人性化【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo导读github.com/dustin/go-humanize是一个专注于把机器友好的原始数值转换为人类可读字符串的 Go 工具库把82854982变成83 MB把time.Time变成7 hours ago把1000000变成1,000,000。Grafana Tempo 在 go.mod 中将其以 v1.0.1 版本引入并以 vendor 方式固化在仓库中见 vendor/github.com/dustin/go-humanize用于在日志、测试与输出场景中把内部数值翻译成直观表达。读完本文你将掌握该库全部核心 API 的用法、输出规则与底层实现原理并能在自己的 Go 项目中直接复用这些能力。一、库概览一行go get就能引入的纯标准库工具go-humanize 的定位非常轻量整个核心包只依赖 Go 标准库fmt、strconv、math、sort、time、regexp等没有任何外部运行时依赖符合 Tempo minimal dependency 的设计取向。引入方式在 README.markdown 中说明import github.com/dustin/go-humanize使用时以humanize作为包名即可。它提供的功能按主题可分为六大类Sizes字节数的人性化展示与反向解析Times相对时间表达3 天前Ordinals序数词1st / 2nd / 3rdCommas千分位分组Ftoa去除尾随零的浮点格式化SI notation国际单位制前缀k/M/G/n 等。另有humanize/english子包处理英文复数与词列连接。全部函数都在包的 humanize.go 与各主题源码文件中给出实现下文逐一展开。二、Sizes字节数的双轨制格式化SI 与 IEC这是整个库中使用频率最高的功能。核心目标是把类似82854982的裸字节数转换成用户一眼能读懂的83 MB或79 MiB。2.1 两个入口Bytes与IBytesfmt.Printf(That file is %s., humanize.Bytes(82854982)) // That file is 83 MB.Bytes(s uint64)使用SI 单位制以 1000 为底后缀序列为B / kB / MB / GB / TB / PB / EBIBytes(s uint64)使用IEC 单位制二进制倍数以 1024 为底后缀序列为B / KiB / MiB / GiB / TiB / PiB / EiB。两者共享同一个底层算法humanateBytes见 bytes.gofunc humanateBytes(s uint64, base float64, sizes []string) string { if s 10 { return fmt.Sprintf(%d B, s) } e : math.Floor(logn(float64(s), base)) suffix : sizes[int(e)] val : math.Floor(float64(s)/math.Pow(base, e)*100.5) / 10 f : %.0f %s if val 10 { f %.1f %s } return fmt.Sprintf(f, val, suffix) }实现要点指数e通过对数log_base(s)取整得到从而确定落在哪一级后缀结果值保留1 位小数四舍五入到十分位当换算后的数值 ≥ 10 时退化为整数展示小于 10 字节的数字直接原样输出不做任何换算。2.2 单位常量与反向解析ParseBytes源码中定义了两套单位常量bytes.goIECByte 1 (iota * 10)依次得到KiByte / MiByte / GiByte / TiByte / PiByte / EiByte每级 ×1024SIKByte IByte * 1000依次得到MByte / GByte / TByte / PByte / EByte每级 ×1000。与正向格式化对应ParseBytes能把字符串解析回字节数bytes.go支持数字部分含.与,逗号会被剥离单位部分不区分大小写并支持无后缀的简写形式如k、m、ki、mi。示例humanize.ParseBytes(42 MB) // - 42000000, nil humanize.ParseBytes(42 mib) // - 44040192, nil若后缀无法识别不在bytesSizeTable中会返回unhandled size name: ...错误若换算结果超过math.MaxUint64会返回too large错误。2.3 大数据量版本bigbytes.go对于超出uint64范围的超大数值同目录下的 bigbytes.go 提供了基于math/big的BigBytes/BigIBytes/ParseBigBytes思路与上面一致只是底层换成大整数运算。三、Times把time.Time变成多久之前 / 多久之后3.1 最简用法Timefmt.Printf(This was touched %s., humanize.Time(someTimeInstance)) // This was touched 7 hours ago.Time(then time.Time)内部等价于RelTime(then, time.Now(), ago, from now)见 times.go过去的时间点后缀ago未来的时间点后缀from now。3.2 相对时间算法RelTime与CustomRelTimeRelTime(a, b, albl, blbl)比较两个时间点时间在前者使用albl标签在后者使用blbl标签CustomRelTime(a, b, albl, blbl, magnitudes)允许传入自定义的分档表。核心算法times.go计算diff b.Sub(a)若a晚于b则交换方向并切换标签用sort.Search在分档表magnitudes中二分查找第一个D diff的档位按该档位的Format模板填充%s替换为方向标签%d替换为diff / DivBy。3.3 默认分档表可直接参照的展示规则默认档位定义在 times.go这里完整列出时间差范围输出格式换算除数 1 秒now— 2 秒1 second %s— 1 分钟%d seconds %s秒 2 分钟1 minute %s— 1 小时%d minutes %s分钟 2 小时1 hour %s— 1 天%d hours %s小时 2 天1 day %s— 1 周%d days %s天 2 周1 week %s— 1 月30 天%d weeks %s周 2 月1 month %s— 1 年%d months %s月 18 月1 year %s— 2 年2 years %s— 37 年%d years %s年更长a long while %s—其中Day 24h、Week 7 * Day、Month 30 * Day、Year 12 * Month、LongTime 37 * Year都在 times.go 中定义。可以看出该库对1 个单位如 1 second、1 minute、1 day使用单数固定模板大于 1 个单位的差值才进入多单位 数字模板这正是它输出自然度的来源。四、Ordinals序数词输出序数功能源自 Go 邮件列表的一次讨论用于把整数变成序数表达0 - 0th 1 - 1st 2 - 2nd 3 - 3rd 4 - 4th用法README.markdownfmt.Printf(Youre my %s best friend., humanize.Ordinal(193)) // You are my 193rd best friend.实现ordinals.go只依赖strconv规则符合英语习惯默认后缀th仅当个位数为 1/2/3 且不是11/12/13即x%100不为 11/12/13时才改用st/nd/rd。五、Commas千分位分组5.1Commaint64fmt.Printf(You owe $%s.\n, humanize.Comma(6582491)) // You owe $6,582,491.行为示例0 → 0、100 → 100、1000 → 1,000、1000000000 → 1,000,000,000、-100000 → -100,000。实现要点comma.go负号单独提取负数绝对值参与分组从低位起每 3 位切一段不足 3 位时左侧补0再拼接特殊处理math.MinInt64因为MinInt64无法被安全取负直接返回硬编码字符串-9,223,372,036,854,775,808。5.2Commaf与CommafWithDigitsfloat64humanize.Commaf(834142.32) // 834,142.32 humanize.CommafWithDigits(834142.32, 1) // 834,142.3Commafcomma.go先按strconv.FormatFloat(v, f, -1, 64)转字符串再拆分整数部分分组小数部分原样保留CommafWithDigits进一步用stripTrailingDigits限制小数位数。5.3BigCommabig.Int对math/big大整数做同样分组的BigCommacomma.go适合超大数值展示。六、Ftoa去掉尾随零的浮点格式化Go 自带的%f会固定输出 6 位小数产生2.240000、2.000000这种机器味很重的表达go-humanize 用Ftoa解决fmt.Printf(%f, 2.24) // 2.240000 fmt.Printf(%s, humanize.Ftoa(2.24)) // 2.24 fmt.Printf(%f, 2.0) // 2.000000 fmt.Printf(%s, humanize.Ftoa(2.0)) // 2实现ftoa.go先按f格式输出 6 位小数再通过stripTrailingZeros从右向左删除尾随0遇到小数点也一并删掉最终得到无尾随零的紧凑字符串。配套的FtoaWithDigits(num, digits)则先把结果截断到指定小数位数再去零例如FtoaWithDigits(3.14159, 2)得到3.14。七、SI notation科学计数的人类友好化7.1 正向输出SI/SIWithDigitshumanize.SI(0.00000000223, M) // 2.23 nMSI(input, unit)会把任意数量级的值换算到最合适的 SI 前缀上前缀取自完整的国际单位制表si.go覆盖从qquecto10⁻³⁰到Qquetta10³⁰的 21 个量级其中包含小量级nnano10⁻⁹、µmicro10⁻⁶、mmilli10⁻³无量级10⁰大量级kkilo10³、Mmega10⁶、Ggiga10⁹、Ttera10¹²等。数值部分复用Ftoa去除尾随零因此SI(1000000, B)输出1 MB。SIWithDigits(input, decimals, unit)可额外限制小数位数。7.2 计算层ComputeSIComputeSI(input) (float64, string)si.go返回调整后的数值 前缀算法为取绝对值 → 以 10 为底对数向下取整 → 再向下归整到 3 的倍数Floor(exponent/3)*3→ 数值除以对应 10 的幂。它特殊处理了换算后恰好为1000.0的情况此时进位例如1000 k归一为1 M。7.3 反向解析ParseSIParseSI(2.2345 pF) - (2.2345e-12, F, nil)通过init()中动态构建的正则si.go拆出数字、前缀与单位再用反向前缀表revSIPrefixTable值为10^指数还原数值。八、English 子包英文复数与词列连接humanize/english子包提供面向英文文案的辅助函数原文档README.markdown给出了完整示例8.1 复数english.PluralWord(1, object, ) // object english.PluralWord(42, object, ) // objects english.PluralWord(2, bus, ) // buses english.PluralWord(99, locus, loci) // loci english.Plural(1, object, ) // 1 object english.Plural(42, object, ) // 42 objects english.Plural(2, bus, ) // 2 buses english.Plural(99, locus, loci) // 99 lociPluralWord只返回单词本身单数或复数形式数量为 1 时返回单数原词否则按规则加s第三个参数允许提供不规则复数如locus → lociPlural返回数字 空格 单词的完整表达。8.2 词列Word seriesenglish.WordSeries([]string{foo}, and) // foo english.WordSeries([]string{foo, bar}, and) // foo and bar english.WordSeries([]string{foo, bar, baz}, and) // foo, bar and baz english.OxfordWordSeries([]string{foo, bar, baz}, and) // foo, bar, and bazWordSeries用连接词如and拼接英文列表超过两个元素时用逗号分隔并在最后一个元素前插入连接词OxfordWordSeries额外在连接词前加上牛津逗号foo, bar, and baz。注在 Tempo 仓库的 vendor 目录中vendor/github.com/dustin/go-humanize 固化的是核心包文件bytes.go、comma.go、ftoa.go、si.go、times.go、ordinals.go、big.go、bigbytes.go、number.go、humanize.go等english子包按原文档说明位于humanize/english本文以其文档示例为准。九、在 Tempo 仓库中的实际使用场景go-humanize 在 Tempo 中以 vendor 依赖形式存在go.mod 声明github.com/dustin/go-humanize v1.0.1vendor/modules.txt 记录其 vendor 条目。它的典型价值在于把调试输出变得直观例如在 modules/generator/processor/spanmetrics/spanmetrics_test.go 的测试日志中通过humanize.Bytes(uint64(batch.Size()))打印 batch 大小让82854982这样的原始字节数在测试输出里变成一眼可读的83 MB形式。这种数字 → 人类可读字符串的转换在分布式追踪系统的日常运维中尤其有用块block大小、批次字节数、历史时间戳、基数统计等原始数值经过Bytes/Time/Comma格式化后日志与指标面板的可读性会显著提升。你可以在自己的监控组件或工具链中以完全相同的方式引入并使用这套 API。十、小结与最佳实践字节展示日志与 UI 中默认推荐IBytesIEC 语义避免 1024/1000 混淆面向客户或通用场景可选BytesSI 语义需要还原数值时用ParseBytes配合完整后缀表。相对时间默认Time的档位模板已经足够自然如果产品有特殊粒度需求如精确到天、弱化分钟用CustomRelTime传入自定义RelTimeMagnitude分档表即可注意模板中%s方向标签与%d数量的占位约定。数字格式化整数分组用Comma浮点分组用Commaf去除尾随零用Ftoa跨数量级换算用SI/SIWithDigits超大数使用BigComma/BigBytes。英文文案拼接日志或错误提示中的数量词时用english.Plural/PluralWord并记得为不规则名词提供第三个参数。引用方式本文全部实现细节均可直接在仓库的 vendor/github.com/dustin/go-humanize 目录下逐文件核对涉及的具体文件包括 bytes.go、times.go、comma.go、ftoa.go、si.go 与 ordinals.go。【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Nacos MCP Router 的 mcp_servers 一多就靠手改?让 Codex 走 TaoToken 通道按 stdio/SSE 分类整理

Nacos MCP Router 的 mcp_servers 一多就靠手改?让 Codex 走 TaoToken 通道按 stdio/SSE 分类整理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 22:35:44 阅读更多 →
Miniflare 中的变量与密钥绑定:在 Cloudflare Workers 本地测试中注入 Variables、Secrets 与 Blob 资源

Miniflare 中的变量与密钥绑定:在 Cloudflare Workers 本地测试中注入 Variables、Secrets 与 Blob 资源

Miniflare 中的变量与密钥绑定:在 Cloudflare Workers 本地测试中注入 Variables、Secrets 与 Blob 资源 【免费下载链接】cloudflare-docs Cloudflare’s documentation 项目地址: https://gitcode.com/GitHub_Trending/cl/cloudflare-docs 本文基于 cloudf…

2026/9/18 22:35:44 阅读更多 →
Creo ptcdbatch 转 stp 卡住?把 Codex 的 Base URL 改到 TaoToken 再排查 dxc

Creo ptcdbatch 转 stp 卡住?把 Codex 的 Base URL 改到 TaoToken 再排查 dxc

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 22:35:44 阅读更多 →

最新新闻

Unity Addressables构建全解析:原理、实操与优化指南

Unity Addressables构建全解析:原理、实操与优化指南

做Unity项目做久了,资源这块迟早会撞上Addressables。不少朋友在群里问,说照着官方文档看完前面几章,加载、卸载、依赖管理都跑通了,结果卡在最后一步构建上,出包量大、加载卡顿、ab包文件对不上,甚至构建一…

2026/9/18 23:18:06 阅读更多 →
oh-my-hermes:统一 Hermes 配置管理,让 React Native 性能优化更简单

oh-my-hermes:统一 Hermes 配置管理,让 React Native 性能优化更简单

1. 项目缘起:为什么我会折腾一套 Hermes 配置管理方案先交代一下背景。我一直在做 React Native 相关的性能优化工作,接触 Hermes 引擎其实比大多数人要早。Hermes 是 Facebook 专门为 React Native 打造的那套 JavaScript 引擎,它在 Android…

2026/9/18 23:18:06 阅读更多 →
FastStream 文档贡献指南:从本地构建到可测试代码示例的完整流程

FastStream 文档贡献指南:从本地构建到可测试代码示例的完整流程

FastStream 文档贡献指南:从本地构建到可测试代码示例的完整流程 【免费下载链接】faststream Asynchronous Python framework for event-driven services. A thin client for Kafka, RabbitMQ, NATS, Redis and MQTT with full access to native broker features, …

2026/9/18 23:18:06 阅读更多 →
UE高级运动系统实战:数据流、动画融合与性能优化

UE高级运动系统实战:数据流、动画融合与性能优化

1. 先把"高级运动系统"的边界划清楚1.1 高级运动系统究竟在解决什么问题刚接触 UE高级运动系统 的人,十有八九是被那种"转身会甩腿、跑动会压身、上下坡脚步能贴地"的角色手感吸引过来的。但真把工程拖进编辑器跑起来,往往第一反应是…

2026/9/18 23:18:06 阅读更多 →
CANN Runtime 模型运行时实例(Model RI)任务更新实战:基于 aclmdlRICaptureTaskGrp 与 aclmdlRICaptureTaskUpdate 的算子级模型更新

CANN Runtime 模型运行时实例(Model RI)任务更新实战:基于 aclmdlRICaptureTaskGrp 与 aclmdlRICaptureTaskUpdate 的算子级模型更新

CANN Runtime 模型运行时实例(Model RI)任务更新实战:基于 aclmdlRICaptureTaskGrp 与 aclmdlRICaptureTaskUpdate 的算子级模型更新 【免费下载链接】runtime 本项目提供CANN运行时组件和维测功能组件。 项目地址: https://gitcode.com/ca…

2026/9/18 23:18:06 阅读更多 →
Cursor 用 Ctrl+K 写冒泡排序,Base URL 填 TaoToken

Cursor 用 Ctrl+K 写冒泡排序,Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 23:17:06 阅读更多 →

日新闻

Matlab手写逻辑回归:从数学原理到多变量概率预测模型实现

Matlab手写逻辑回归:从数学原理到多变量概率预测模型实现

很多朋友第一次看到"逻辑回归"这四个字,第一反应就是——这玩意儿是个回归模型吧?我当年也是在Matlab里跑完一段代码,看着输出的0.73、0.86这种概率值,才回过神来:这家伙其实是披着回归外衣的分类神器&#…

2026/9/18 0:00:28 阅读更多 →
高值医用耗材研报PDF:用Python完成字段抽取、清洗与趋势预测

高值医用耗材研报PDF:用Python完成字段抽取、清洗与趋势预测

简介:这份报告是2023-2028年高值医用耗材行业调研及发展前景趋势预测报告,面向医疗器械企业管理者、投资机构、行业研究人员及关注政策变化的从业者,用于把握行业监管动向、市场格局与未来趋势。报告以PDF格式呈现,共1个文件、整体…

2026/9/18 0:00:28 阅读更多 →
三维高斯场赋能世界模型:几何语义蒸馏与机器人决策实战

三维高斯场赋能世界模型:几何语义蒸馏与机器人决策实战

先把我自己的背景交代一下:我之前在搞具身智能和机器人导航相关的项目,很长一段时间里都被“环境表示”这件事卡着。传统做法是用点云或者网格做几何建模,语义信息另外再跑分割模型,两套东西各管各的,时间一长就会发现…

2026/9/18 0:00:28 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/16 19:03:19 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/17 7:57:36 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/17 10:19:14 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/15 21:39:18 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →