当前位置: 首页 > news >正文

GO 中高效 int 转换 string 的方法与高性能源码剖析


文章目录

    • 使用 `strconv.Itoa`
    • 使用 `fmt.Sprintf`
    • 使用 `strconv.FormatInt`
    • FormatInt 深入剖析
      • 1. 快速路径处理小整数
      • 2. formatBits 函数的高效实现
    • 结论

Go 语言 中,将整数(int)转换为字符串(string)是一项常见的操作。

本文将从逐步介绍几种在 Go 中将 int 转换为 string 的常见方法,并重点剖析这几种方法在性能上的特点。另外,还会重点介绍 FormatInt 高效的算法实现。

在这里插入图片描述

使用 strconv.Itoa

最直接且常用的方法是使用 strconv 包中的 Itoa 函数。Itoa 是 “Integer to ASCII” 的简写,它提供了一种快速且简洁的方式实现整数到字符串之间的转换。

示例代码如下:

package mainimport ("strconv""fmt"
)func main() {i := 123s := strconv.Itoa(i)fmt.Println(s)
}

strconv.Itoa 是通过直接将整数转换为其 ASCII 字符串表示形式。这个过程中尽量减少了额外的内存分配,没有复杂逻辑。

使用 fmt.Sprintf

另一种方法是,使用 fmt 包的 Sprintf 函数。这个方法在功能上更为强大和灵活,因为它能处理各种类型并按照指定的格式输出。

示例代码如下:

package mainimport ("fmt"
)func main() {i := 123s := fmt.Sprintf("%d", i)fmt.Println(s)
}

虽然 fmt.Sprintf 在功能上非常强大,但它的性能通常不如 strconv.Itoa

为什么呢?

因为 fmt.Sprintf 内部使用了反射(reflection)确定输入值类型,并且在处理过程中涉及到更多的字符串拼接和内存分配。

使用 strconv.FormatInt

当需要更多控制或处理非 int 类型的整数(如 int64)时,可以使用 strconv 包的 FormatInt 函数。

package mainimport ("strconv""fmt"
)func main() {var i int64 = 123s := strconv.FormatInt(i, 10)  // 10 表示十进制fmt.Println(s)
}

strconv.FormatInt 提供了对整数转换过程的更细粒度控制,包括 base 的选择(例如,十进制、十六进制等)。

strconv.Itoa 类似,FormatInt 在性能上也非常可观,而且 FormatInt 提供了既灵活又高效的解决方案。

如果我们查看 strconv.Itoa 源码,会发现 strconv.Itoa 其实是 strconv.FormatInt 的一个特殊情况。

// Itoa is shorthand for FormatInt(int64(i), 10).
func Itoa(i int) string {return FormatInt(int64(i), 10)
}

现在 int 转 string 的高性能源码剖析,就变成了重点剖析 FormatInt

FormatInt 深入剖析

基于 Go 1.21 版本的 itoa.go 源码,我们可以深入理解 strconv 包中整数到字符串转换函数的高效实现。

func FormatInt(i int64, base int) string {if fastSmalls && 0 <= i && i < nSmalls && base == 10 {return small(int(i)) // 100 以内的十进制小整数,使用 small 函数转化}_, s := formatBits(nil, uint64(i), base, i < 0, false) // 其他情况使用 formatBitsreturn s
}

以下是对其核心部分的详细解读,将会突出了其性能优化的关键方面,结合具体的源码实现说明。

在这里插入图片描述

1. 快速路径处理小整数

对于常见的小整数,strconv 包提供了一个快速路径,small 函数,直接返回预先计算好的字符串,避免了运行时的计算开销。

func small(i int) string {if i < 10 {return digits[i : i+1]}return smallsString[i*2 : i*2+2]
}

对于小于 100 的十进制整数,采用这个快速实现方案,或许这也是整数转字符串的最常见使用场景吧。

small 函数通过索引到 smallsStringdigits 获取小整数的字符串表示,这个过程非常快速。

digitssmallsString 的值,如下所示:

const smallsString = "00010203040506070809" +"10111213141516171819" +"20212223242526272829" +"30313233343536373839" +"40414243444546474849" +"50515253545556575859" +"60616263646566676869" +"70717273747576777879" +"80818283848586878889" +"90919293949596979899"const digits = "0123456789abcdefghijklmnopqrstuvwxyz"

它们也就是十进制 0-99 与对应字符串的映射。

2. formatBits 函数的高效实现

FormatInt 最复杂的部分是 formatBits 函数,它是整数到字符串转换的核心,它针对不同的基数进行了优化。

在这里插入图片描述

10进制转换的优化

对于10进制转换,formatBits 使用了基于除法和取余的算法,并通过 smallsString 加速两位数的字符串获取。

if base == 10 {// ... (32位系统的优化)us := uint(u)for us >= 100 {is := us % 100 * 2us /= 100i -= 2a[i+1] = smallsString[is+1]a[i+0] = smallsString[is+0]}// ... (处理剩余的数字)
}
  • 对于 32 位系统,使用32位操作处理较大的数字,减少 64 位除法的开销。
  • 每次处理两位数字,直接从 smallsString 获取对应的字符,避免了单独转换每一位的开销。

2的幂基数的优化

对于基数是2的幂的情况,formatBits 使用了位操作来优化转换。

} else if isPowerOfTwo(base) {shift := uint(bits.TrailingZeros(uint(base))) & 7b := uint64(base)m := uint(base) - 1 // == 1<<shift - 1for u >= b {i--a[i] = digits[uint(u)&m]u >>= shift}// u < basei--a[i] = digits[uint(u)]
}
  • 位操作是直接在二进制上进行,比除法和取余操作更快。
  • 利用 2 的幂基数的特性,通过移位和掩码操作获取数字的各个位。

通用情况的处理

对于其他基数,formatBits 使用了通用的算法,但仍然尽量减少了除法和取余操作的使用。

} else {// general caseb := uint64(base)for u >= b {i--// Avoid using r = a%b in addition to q = a/b// since 64bit division and modulo operations// are calculated by runtime functions on 32bit machines.q := u / ba[i] = digits[uint(u-q*b)]u = q
}

我觉得最核心的算法就是利用移位和特殊路径预置映射关系。另外,由于算法足够优秀,还避免了一些不必要内存分配。

结论

将 int 转化为 string 是一个非常常见的需求。Go 语言的 strconv 包中的 int 到 string 的转换函数展示了 Go 标准库对性能的深刻理解和关注。

通过快速处理小整数、优化的 10 进制转换算法、以及2^n 基数的特别处理,这些函数能够提供高效且稳定的性能。这些优化确保了即使在大量数据或在性能敏感的场景中,strconv 包的函数也能提供出色的性能

博文地址:GO 中高效 int 转换 string 的方法与源码剖析

相关文章:

GO 中高效 int 转换 string 的方法与高性能源码剖析

文章目录 使用 strconv.Itoa使用 fmt.Sprintf使用 strconv.FormatIntFormatInt 深入剖析1. 快速路径处理小整数2. formatBits 函数的高效实现 结论 Go 语言 中&#xff0c;将整数&#xff08;int&#xff09;转换为字符串&#xff08;string&#xff09;是一项常见的操作。 本文…...

YOLOv7调用摄像头检测报错解决

yolov7detect.py文件调用本地摄像头&#xff0c;把source参数设为0 parser.add_argument(--source, typestr, default0, helpsource) # file/folder, 0 for webcam 报错&#xff1a;cv2.error: OpenCV(3.4.2) 一堆地址:The function is not implemented. Rebuild the library…...

Git学习 -- 分支合并、版本修改相关

目录 learn GIT Learn Git Branching merge和rebase的使用 基础命令 版本回退 工作区和暂存区 管理修改 撤销修改 删除修改 learn GIT Learn Git Branching 这是Gitee上的Git学习教程 Learn Git Branching Git Rebase Learn Git Branching 最终的实操 merge和rebase的…...

【小呆的力学笔记】弹塑性力学的初步认知二:应力应变分析(2)

文章目录 1.4 主应力空间、八面体应力1.5 应变分析1.6 特殊应力、应变定义 1.4 主应力空间、八面体应力 一点的应力状态不论如何变化&#xff0c;其主应力和主方向一致的话&#xff0c;该点的应力状态就是唯一确定的。因此&#xff0c;我们用主应力方向建立一个三维坐标系来描…...

【学网攻】 第(6)节 -- 三层交换机实现VLAN间路由

文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学网攻】 第(3)节 -- 交换机配置聚合端口【学网攻】 第(4)节 -- 交换机划分Vlan【学网攻】 第(5)节 -- Cisco VTP的使用 前言 网络已经成为了我们生活中不可或缺的一部分&#xff0c;它连接了…...

C++之内联函数

函数调用在执行时&#xff0c;首先要在栈中为形参和局部变量分配存储空间&#xff0c;然后还要将实参的值复制给形参&#xff0c;接下来还要将函数的返回地址&#xff08;该地址指明了函数执行结束后&#xff0c;程序应该回到哪里继续执行&#xff09;放入栈中&#xff0c;最后…...

【Bugku-web】alert

1.打开场景 2.按"CtrlU"查看源代码 3.翻到页面最末尾会有一个HTML实体编码&#xff0c;用在线工具在线Html实体编码解码后&#xff0c;得到flag值。...

QQ数据包解密

Windows版qq数据包格式&#xff1a; android版qq数据包格式&#xff1a; 密钥&#xff1a;16个0 算法&#xff1a;tea_crypt算法 pc版qq 0825数据包解密源码&#xff1a; #include "qq.h" #include "qqcrypt.h" #include <WinSock2.h> #include…...

腾讯云上linux系统使用nginx,flask构建个人网站SSL证书过期换证书的操作步骤

ssl证书过期的时候&#xff0c;一般腾讯云提前一段时间给通知&#xff0c;让更换ssl证书&#xff0c;现在一般都可以免费更换&#xff0c;一般是一年期的&#xff0c;审核通过之后&#xff0c;需要下载nginx版本的证书&#xff0c;我的是4个文件&#xff0c;替换到nginx/cert文…...

git-clone的single-branch操作回退

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 最近使用git越来越多&#xff0c;一些git的功能使用也更熟悉了一些。 之前使用了single-branch下载分支&#xff0c;后来想取消掉&#xff0c;但怎么做呢&#xff0c;查了一些资料之后&#xff0c;了解到了怎么做&#x…...

03 SpringBoot实战 -微头条之首页门户模块(跳转某页面自动展示所有信息+根据hid查询文章全文并用乐观锁修改阅读量)

1.1 自动展示所有信息 需求描述: 进入新闻首页portal/findAllType, 自动返回所有栏目名称和id 接口描述 url地址&#xff1a;portal/findAllTypes 请求方式&#xff1a;get 请求参数&#xff1a;无 响应数据&#xff1a; 成功 {"code":"200","mes…...

YOCTO基础 - 创建meta层与bb文件

背景 在当前的嵌入式系统开发项目中&#xff0c;我们面临着构建定制化 Linux 发行版以满足项目需求的挑战。我们需要在目标硬件上运行一个轻量级、高度定制化的 Linux 映像&#xff0c;并确保它包含我们项目中所需的特定软件包和功能。为了实现这一目标&#xff0c;我们选择了…...

网络电视盒子哪个好?博主分享超高性价比网络电视盒子推荐

电视盒子是我们使用最多的数码产品&#xff0c;年货节很多朋友在纠结网络电视盒子哪个好&#xff0c;我这次的测评产品就是电视盒子&#xff0c;按照18款电视盒子的深度测评结果整理了网络电视盒子推荐&#xff0c;想知道网络电视盒子哪个好可以看看下面这五款电视盒子。 一&am…...

leetcode 刷题2

二分查找的绝妙运用&#xff1a; 看到有序数列&#xff0c;算法复杂度 0033. 搜索旋转排序数组 class Solution { public:int search(vector<int>& nums, int target) {int left 0;int right nums.size() - 1;while (left < right) {int mid left (right - …...

2-SAT问题相关理论和算法

前言 SAT 问题简介 SAT是可满足性、适定性(Satisfiability)问题的简称。一般形式为k-适定性问题或k-可满足性问题&#xff0c;简称 k-SAT。 何为布尔可满足性问题&#xff1f;给定一条真值表达式&#xff0c;包含逻辑变量、逻辑与、逻辑或以及非运算符&#xff0c;如&#x…...

【大数据精讲】全量同步与CDC增量同步方案对比

目录 背景 名词解释 问题与挑战 FlinkCDC DataX 工作原理 调度流程 五、DataX 3.0六大核心优势 性能优化 背景 名词解释 CDC CDC又称变更数据捕获&#xff08;Change Data Capture&#xff09;&#xff0c;开启cdc的源表在插入INSERT、更新UPDATE和删除DELETE活动时…...

自定义通用返回对象

目的&#xff1a;给返回对象补充一些信息&#xff0c;告诉前端这个请求在业务层面上是成功还是失败&#xff0c;以及具体的描述信息。 我们需要自定义错误码&#xff08;因为前端的HTTP状态码默认的值比较少&#xff09;和正常错误返回类。 ErrorCode &#xff1a; package …...

从0开始python学习-51.pytest之接口加密封装

目录 MD5加密 base64加密 rsa加密 MD5加密 1. 封装加密方法 def md5_encode(self,data):data str(data).encode("utf-8")md5_data hashlib.md5(data).hexdigest()return md5_data 2. 写入需要使用加密的接口yaml用例 -request:method: posturl: http://192.168.…...

c++的命名空间

命名空间 一.c的关键字二.命名空间2.1 命名空间定义2.1 命名空间的使用2.1.1加命名空间名称及作用域限定符2.1.2使用using将命名空间中某个成员引入 三.标准命名空间std 一.c的关键字 c中一共有63个关键字 关键字11111asmdoifreturntrycontinueautodoubleinlineshorttypedeff…...

阿富汗塔利班兴起时的比赛代码3475:练85.3 删数问题(Noip1994)

【题目描述】 输入一个高精度的正整数n&#xfffd;&#xff0c;去掉其中任意s&#xfffd;个数字后剩下的数字按原左右次序组成一个新的正整数。编程对给定的n&#xfffd;和s&#xfffd;&#xff0c;寻找一种方案使得剩下的数字组成的新数最小。 输出新的正整数。&#xff0…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...