Go 人性化数字格式化完整指南:go-humanize 的尺寸、时间、序数与 SI 单位格式化实战

发布时间:2026/9/17 17:05:16

Go 人性化数字格式化完整指南:go-humanize 的尺寸、时间、序数与 SI 单位格式化实战 Go 人性化数字格式化完整指南go-humanize 的尺寸、时间、序数与 SI 单位格式化实战【免费下载链接】inngestThe leading workflow orchestration platform. Run stateful step functions and AI workflows on serverless, servers, or the edge.项目地址: https://gitcode.com/GitHub_Trending/in/inngestgo-humanize是一套把枯燥丑陋的数字转换为人友好字符串的 Go 工具库它能将82854982变成83 MB将time.Time输出为3 days ago还能处理序数词、千分位逗号、浮点去尾零以及 SI 科学计数法。本文以仓库内 vendored 的 README.markdown 为主体骨架结合其位于 vendor/github.com/dustin/go-humanize 下的完整源码实现当前仓库在 go.mod 中声明依赖github.com/dustin/go-humanize v1.0.1逐函数讲解 API 用法、底层算法与边界行为让读者既能直接上手也能理解每个格式化函数背后的实现原理。安装与引入README 给出的引入方式非常直接使用go get拉取依赖导入路径为github.com/dustin/go-humanize包名use it as为humanizeimport github.com/dustin/go-humanize在 go.mod 中可以看到当前仓库将其以v1.0.1版本记录为 indirect 依赖并在vendor/github.com/dustin/go-humanize/目录下完整保留了该库的源码bytes.go、times.go、comma.go、si.go、ordinals.go、ftoa.go、big.go、bigbytes.go、number.go等。下面按功能模块逐一展开。字节大小格式化Sizes这是 go-humanize 最常用的功能把数字字节数转换为可读的容量字符串例如82854982可输出为83 MBSI 十进制或79 MiBIEC 二进制完全由你选择。fmt.Printf(That file is %s., humanize.Bytes(82854982)) // That file is 83 MB.从 bytes.go 的实现可以看到两个核心函数Bytes(s uint64) stringbytes.go以 1000 为底数后缀序列为B, kB, MB, GB, TB, PB, EB输出十进制SI容量。IBytes(s uint64) stringbytes.go以 1024 为底数后缀序列为B, KiB, MiB, GiB, TiB, PiB, EiB输出二进制IEC容量。两者的底层都调用同一个私有函数humanateBytesbytes.go其算法要点如下小于 10 字节时直接输出%d B不做单位换算使用lognbytes.go即math.Log(n) / math.Log(b)计算以 base 为底的对数取math.Floor得到数量级指数e数值按math.Floor(float64(s)/math.Pow(base, e)*100.5)/10保留一位小数四舍五入若结果小于 10 用%.1f %s否则用%.0f %s抹掉小数。单位常量与解析源码中还定义了两组可直接引用的常量IEC 常量bytes.goByte 1 (iota * 10)即KiByte1024、MiByte120、GiByte、TiByte、PiByte、EiByteSI 常量bytes.goIByte 1、KByte 1000、MByte、GByte、TByte、PByte、EByte按千进位。与之配套的解析函数ParseBytes(s string) (uint64, error)bytes.go可以把字符串反解回字节数例如42 MB - 42000000、42 mib - 44040192。它内部通过bytesSizeTablebytes.go查表该表同时收录了带完整后缀b/kib/kb/...和省略后缀ki/k/m/...的写法且解析时大小写不敏感如果数字部分含逗号会先剥离逗号遇到超出uint64上限的数值会返回too large错误未知单位则返回unhandled size name错误。相对时间格式化Timeshumanize.Time可以把一个time.Time转成相对时间表述例如12 seconds ago或3 days from nowfmt.Printf(This was touched %s., humanize.Time(someTimeInstance)) // This was touched 7 hours ago.README 提到该时间实现源自 Kyle Lemons 在某次 IRC 交流中的想法。从 times.go 可以看到完整的调用链Time(then time.Time) stringtimes.go是对RelTime(then, time.Now(), ago, from now)的封装RelTime(a, b time.Time, albl, blbl string) stringtimes.go提供自定义时间点与标签的能力如RelTime(timeInPast, timeInFuture, earlier, later) - 3 weeks earlierCustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) stringtimes.go允许你完全自定义量级切换表。量级表与二分查找RelTimeMagnitudetimes.go是一个包含D触发阈值时长、Format格式串含%s标签位与%d数量位、DivBy换算除数三个字段的结构体。默认量级表defaultMagnitudestimes.go按时间从短到长排列覆盖now、1 second ago、%d seconds ago、1 minute ago直到%d years ago和最终的a long while ago。格式化时CustomRelTime先根据a.After(b)判断取albl过去ago还是blbl未来from now然后用sort.Search对按D升序排列的量级表做二分查找找到第一个D diff的档位最后解析 Format 中的%s与%d占位符填充标签与数量。时间单位常量times.go中Month 30 * Day、Year 12 * Month、LongTime 37 * Year即一个月约 30 天、一年约 360 天这是相对时间表述的近似约定而非日历计算。序数词格式化Ordinals序数词功能源自一次 golang-nuts 邮件列表讨论用户希望输出排名后缀。其转换规则为0 - 0th 1 - 1st 2 - 2nd 3 - 3rd 4 - 4th [...]fmt.Printf(Youre my %s best friend., humanize.Ordinal(193)) // You are my 193rd best friend.实现位于 ordinals.go默认后缀为th仅当个位为 1/2/3 且整个数字不以 11/12/13 结尾时才分别替换为st/nd/rd从而正确处理11th、12th、13th这些特例。该函数接收int并返回字符串非负数直接拼接负数也会得到-1st之类的结果。千分位逗号格式化Commas想把逗号塞进数字里请便。 README 给出的行为示例0 - 0 100 - 100 1000 - 1,000 1000000000 - 1,000,000,000 -100000 - -100,000fmt.Printf(You owe $%s.\n, humanize.Comma(6582491)) // You owe $6,582,491.从 comma.go 可以读到三个层次的实现Comma(v int64) stringcomma.go对int64每三位插入逗号。一个值得注意的边界处理是math.MinInt64无法直接取反因此被特判返回-9,223,372,036,854,775,808comma.go负数先记录符号再对绝对值分组每组不足三位时用0左补齐Commaf(v float64) stringcomma.go浮点版本如Commaf(834142.32) - 834,142.32小数部分原样保留CommafWithDigits(f float64, decimals int) stringcomma.go限制小数位数如CommafWithDigits(834142.32, 1) - 834,142.3BigComma(b *big.Int) stringcomma.go为math/big的大整数提供同样的千分位格式配合 big.go 中的oom数量级计算可格式化超出int64范围的超大数。浮点去尾零格式化Ftoa标准库的%f会输出固定小数位导致2.24变成2.240000。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先用strconv.FormatFloat(num, f, 6, 64)固定输出 6 位小数再由stripTrailingZerosftoa.go从尾部向前裁剪多余的0遇到小数点本身也一并去掉因此2.0输出为2。配套的FtoaWithDigits(num, digits)ftoa.go先裁剪到指定小数位再去除尾零。SI 科学计数法格式化SI notationSI 模块使用 SI 前缀metric prefix 格式化任意数量级的数字例如humanize.SI(0.00000000223, M) // 2.23 nM在 si.go 中前缀表siPrefixTablesi.go覆盖从qquecto10⁻³⁰到Qquetta10³⁰的全部 21 个 SI 前缀含µmicro这样的 Unicode 字符。核心函数ComputeSI(input float64) (float64, string)si.go计算最合适的指数指数按math.Floor(exponent/3)*3对齐到三位一组还处理了value 1000.0时应返回 1 M 而不是 1000 k的特例SI(input float64, unit string) stringsi.go使用Ftoa格式化数值并拼接前缀与单位如SI(1000000, B) - 1 MB、SI(2.2345e-12, F) - 2.2345 pFSIWithDigits(input, decimals, unit)si.go限制小数位如SIWithDigits(1000000, 0, B) - 1 MBParseSI(input string) (float64, string, error)si.go反向解析如ParseSI(2.2345 pF) - (2.2345e-12, F, nil)。其解析正则riParseRegexsi.go在init()中根据前缀表动态拼装而成。大数容量格式化BigBytes 系列README 未单独介绍、但同仓库内一并提供的能力是math/big大数版本。在 bigbytes.go 中BigBytes(s *big.Int) stringbigbytes.go与BigIBytes(s *big.Int) stringbigbytes.go分别以 1000/1024 为底后缀扩展到了ZB, YB, RB, QB对应 IEC 的ZiB, YiB, RiB, QiB可格式化任意大的字节数常量BigKiByte到BigQiBytebigbytes.go通过big.Int乘法逐级构建ParseBigBytesbigbytes.go用big.Rat做有理数运算后整除得到字节数避免浮点精度损失。其格式化辅助函数humanateBigBytesbigbytes.go依赖 big.go 中的oomm/oombig.go做基于big.Int的除模迭代来计算数量级。自定义模板格式化FormatFloat / FormatIntegernumber.go 提供了另一套按模板字符串渲染数字的能力改编自 gorhill 的 gist 实现。FormatFloat(format string, n float64) stringnumber.go使用#,###.##这类格式串控制千分位分隔符、小数分隔符与精度例如n 12345.6789#,###.## 12,345.67 #,###. 12,345 #,### 12345,678 默认格式 12,345.67该函数最高支持 9 位小数精度且对NaN、Infinity、-Infinity做了特判处理FormatInteger(format string, n int) stringnumber.go则是面向模板调用的整数便捷版本。英语专属函数humanize/english 子包README 说明以下函数位于humanize/english子包中即导入路径为github.com/dustin/go-humanize/english。复数化Plurals简单的英语复数规则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 lociPlural输出数字 单词组合PluralWord只输出单词本身两个函数都接受第三个参数作为不规则复数形式如locus的loci为空时按规则变化如bus - buses。词串连接Word series把逗号分隔的单词列表用连词连接成通顺的英文短语english.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按a, b and c形式连接OxfordWordSeries则额外在最后一项前保留逗号牛津逗号风格。边界情况与使用注意事项综合上述源码使用 go-humanize 时有几个值得留意的点单位进制要选对Bytes走 1000SIIBytes走 1024IEC。存储厂商与操作系统的口径常不一致展示容量时务必与业务口径统一相对时间只是近似Month/Year分别按 30 天、360 天折算不涉及日历与时区跨月/跨年场景请自行评估是否符合预期序数词特例11/12/13 结尾的数字后缀永远是th11th、12th、13thOrdinal已正确处理Comma的int64下界math.MinInt64被特判为-9,223,372,036,854,775,808其余负数先取绝对值再分组解析函数会返回错误ParseBytes对未知单位返回unhandled size name对超出uint64的值返回too large使用时应处理 errorFtoa固定走 6 位小数先FormatFloat(f, 6)再裁剪尾零超过 6 位的小数位会被截断需要更多精度时可用FtoaWithDigits或直接使用strconv。小结go-humanize 是一个小而精的格式化工具库字节容量SI/IEC 双进制、相对时间、序数词、千分位逗号、浮点去尾零、SI 前缀以及大数版本一应俱全并附带反向解析函数与自定义量级表/格式模板。本文结合仓库中 vendor/github.com/dustin/go-humanize 的完整源码当前依赖版本见 go.mod逐一剖析了各 API 的调用关系与边界处理读者可以在 README.markdown 与上述各.go文件中继续深入研读原始实现与注释。【免费下载链接】inngestThe leading workflow orchestration platform. Run stateful step functions and AI workflows on serverless, servers, or the edge.项目地址: https://gitcode.com/GitHub_Trending/in/inngest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/17 18:15:22

内地专才申请怎样少走弯路?紧扣自身背景匹配对应服务机构

你有没有想过,明明符合条件,却在专才申请上卡了半年?更离谱的是,有人材料齐全、雇主真实聘用,结果还是被拒。这背后,不是运气差,而是对“真实聘用”和“本地难以招聘”的理解偏差。业内有句话&a…

2026/9/17 18:15:22

高通Camera Pipeline XML可视化与拓扑验证

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

2026/9/17 18:15:22

DDR5内存设计核心:JESD305 2022规范下的RDIMM与LRDIMM技术解析

简介:JESD305规范是JEDEC于2022年1月发布的DDR5 LRDIMM与RDIMM共同标准,面向内存模块设计工程师、服务器硬件研发人员及数据中心选型者,旨在统一两类高密度内存模块的接口定义与互操作要求。DDR5作为DDR4的升级版,提供更高带宽与更…

2026/9/17 18:15:22

Qt C++图像处理软件设计:从架构到发布全流程解析

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

2026/9/17 18:10:21

HCIA-Datacom实战:数据封装、VLAN与NAT配置详解

简介:HCIA-Datacom核心技术笔记总结是一份面向网络工程师、网络管理员、学生及企业IT人员的系统学习资料,针对网络协议理解不深、配置经验不足等常见痛点。笔记以清晰的章节结构从网络基础讲起,依次涵盖数据封装、OSI与TCP/IP模型、Wireshark…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/17 0:03:13

WiFi密码安全测试:从原理到实战的字典暴力破解指南

1. 写在前面:我为什么要研究WiFi密码这件事先交代一下背景。我身边有不少朋友,家里的WiFi密码常年是"12345678"或者"88888888",问就是"好记"。直到有一次,隔壁邻居蹭网蹭到我家路由器后台都进不去&…

2026/9/17 0:03:13

redis-py服务控制与监控函数实战:从ping到slowlog的巡检指南

我用 redis-py 写了快五年的业务代码,坦白说,真正让我觉得这个客户端“像一个成熟工具箱”的,不是 get/set 那套基本操作,而是它那批专门做服务控制与状态监控的辅助函数。日常开发里,大家把redis.Redis(host..., deco…

2026/9/17 0:03:13

SpringBoot+Vue3实现中小企业设备管理系统开发实践

1. 项目概述与核心价值中小企业设备管理系统是制造业、服务业等领域的基础信息化工具。传统设备管理往往依赖Excel表格或纸质记录,存在数据孤岛、流程混乱、维护成本高等痛点。这套基于Java SpringBootVue3MyBatis的技术方案,通过前后端分离架构实现了设…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码