当前位置: 首页 > 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…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...