Go 语言 int 类型那么多,到底该用 int 还是 int64?

林舟
林舟
发布时间:2026-08-25| 195人浏览过
原创

前言

在 Go 项目里,int 和 int64 看似只是位宽不同,实际牵涉到平台差异、标准库习惯、数据库映射和前后端传输精度。很多人一开始图省事随手写,后面才在类型转换、JSON 丢精度或跨平台运行时补坑。本文不绕概念,直接按日常业务、跨边界数据和常见陷阱来拆解,帮你快速判断什么场景该默认用 int,什么时候必须明确写成 int64。

在 Go 项目里,int 和 int64 看起来只差几个字符,实际牵涉到平台位宽、标准库接口、数据库字段映射以及跨端传输精度。很多代码里“能跑”的写法,一旦换到 32 位环境、接数据库或过 JSON,就可能出现额外转换甚至溢出问题。下面按“默认怎么选、哪些场景必须固定宽度、有哪些坑要提前避开”三件事展开,帮你把这类选择题变成一套可直接落地的判断规则。

先看清 Go 的整型家族

Go 提供的整型类型并不少,既有固定宽度的有符号、无符号整数,也有与平台相关的类型:

// 有符号整型
int8    // -128 到 127
int16   // -32768 到 32767
int32   // -2147483648 到 2147483647
int64   // -9223372036854775808 到 9223372036854775807

// 无符号整型
uint8   // 0 到 255
uint16  // 0 到 65535
uint32  // 0 到 4294967295
uint64  // 0 到 18446744073709551615

// 平台相关类型
int     // 32位系统是int32,64位系统是int64
uint    // 32位系统是uint32,64位系统是uint64
uintptr // 用于存储指针的整数类型

这里最需要先记住的是:int 不是固定 32 位,也不是固定 64 位,它和运行平台绑定。在 32 位系统上,int 是 4 字节;在 64 位系统上,int 是 8 字节。相比之下,int64 始终是固定的 8 字节。

这也是很多争论的起点:既然现在大多数线上服务跑在 64 位环境,是否可以直接把所有整数都写成 int64?答案并不是绝对否定,但也绝不是“一把梭”。真正的关键,不在于统一写法是否省心,而在于你的值到底是服务于本地计算,还是需要跨平台、跨进程、跨存储边界保持一致。

int 和 int64,到底怎么选

一般业务代码,默认优先用 int

如果整数只是用于普通业务计算,比如数组索引、循环计数器、订单数量、列表长度,优先用 int 通常是更自然的选择。

Go 整型选择判断卡片,展示 int、int64 与具体位宽类型的适用边界。
先判场景,再定类型先看值的用途,再决定是否需要固定宽度,这是 Go 整型选型里最实用的一步。
// 数组索引
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

// 订单数量
orderCount := 100

这么选主要有三个原因。

  1. Go 标准库大量接口直接使用 int。
  2. int 是平台上最顺手的通用整型,日常代码最少折腾。
  3. 能减少显式类型转换,让代码更短也更符合 Go 的习惯。

最典型的例子就是 len()。它返回的就是 int:

s := []string{"a", "b", "c"}
length := len(s) // 返回int类型
fmt.Println(length)

如果你在这种局部逻辑里强行把结果放进 int64,反而会立刻遇到类型不匹配:

// ❌ 编译错误:类型不匹配
var length int64 = len(s)

// ✅ 需要显式转换
var length int64 = int64(len(s))

这类转换单看一次不算麻烦,但一旦出现在切片长度、索引计算、循环边界、标准库调用之间,代码会很快变得别扭。对于只在当前进程内部使用、又不涉及大范围数值的变量,int 往往就是最省事的答案。

需要固定范围和跨平台一致性时,用 int64

一旦整数要穿过“边界”,优先级就变了。这里的边界包括数据库、网络传输、序列化、日志落盘、跨平台运行等。只要你希望这个值不因为平台不同而变化,就应该直接选固定宽度类型,最常见的就是 int64。

典型场景包括:

  • 数据库 ID 字段
  • 时间戳
  • 跨网络传输的数值
  • 可能超过 21 亿的大数值
// 数据库主键ID,用int64更稳妥
type User struct {
    ID int64 `db:"id"`
    Name string
}

// 时间戳,通常用int64
timestamp := time.Now().Unix() // 返回int64

// 处理大数值
bigNumber := int64(9223372036854775807)

尤其是数据库场景,很多表的 BIGINT 字段天然就对应 Go 的 int64。如果模型里写成 int,你可能在当前 64 位机器上暂时感觉不到问题,但从类型表达上,它已经不再准确,也会在驱动映射、扫描赋值、接口约束上增加不必要的不确定性。

时间戳同理。像 time.Now().Unix() 这类 API 已经明确返回 int64,本身就说明这类值的语义偏向“固定宽度、可传输、可存储”,而不是“随平台变化的本地整数”。

已知范围很明确时,再考虑更具体的类型

如果你非常清楚一个字段的数值范围,那么选择最小够用的类型确实可以节省内存。在处理大量对象、长切片或高吞吐数据结构时,这种优化是有实际意义的。

// 年龄,不会超过255,用uint8足够
type Person struct {
    Age uint8
}

// 分数,0-100,用uint8
score := uint8(95)

// 状态码,用int32
statusCode := int32(200)

但这里有个前提:只有在范围确定且确实存在规模收益时,这样做才值得。因为 Go 在很多算术和接口场景里并不会替你自动打通不同整数类型,小类型带来的节省,有时会被频繁的转换抵消掉阅读性和维护性上的成本。

换句话说,uint8、int32 这些类型不是不能用,而是不适合当作日常默认值。它们更像是“表达约束”或“服务于结构优化”的工具,而不是通用替代品。

放到实际场景里看,会更容易判断

Web 后端接口开发

在 Web 后端里,整数往往同时出现在数据库模型、请求参数、业务处理和 JSON 返回结果中。这类代码最适合按字段语义来拆分选择,而不是全都统一一种类型。

Web 后端与算法场景对比图,说明同一项目内不同字段为什么会选择不同整数类型。
同一项目里,类型可以分工一个项目里同时存在 int 和 int64 很正常,关键是字段语义和边界是否清楚。
// 推荐做法
type User struct {
    ID   int64  `json:"id"`   // 数据库ID用int64
    Age  int    `json:"age"`  // 年龄用int足够
    Score int   `json:"score"` // 分数用int
}

这里 ID 用 int64,通常比 int 更稳妥,原因很直接:

  • 数据库自增 ID 可能超过 2147483647
  • 数据要跨语言、跨服务传递时,需要固定宽度
  • 模型字段与数据库类型对应更清晰

而像年龄、分数这类普通业务值,如果只是做常规运算和展示,int 已经够用,代码也更顺手。

算法和数据结构实现

算法题、工具函数、基础数据结构,往往是 int 最舒服的主场。原因不是它“更大”或“更快”,而是它和索引、长度、切片边界天然一致。

// 二分查找
func binarySearch(arr []int, target int) int {
    left, right := 0, len(arr)-1
    for left <= right {
        mid := left + (right-left)/2
        if arr[mid] == target {
            return mid
        } else if arr[mid] < target {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return -1
}

这类逻辑里使用 int 的好处很明确:

  • len() 返回 int
  • 数组和切片索引使用 int
  • 边界计算不需要到处转换类型

如果这里硬换成 int64,每次拿长度、做索引、访问元素时都要来回转换,几乎得不到收益,却会让实现变得更啰嗦。

大量数据与性能敏感结构

当你处理的是上百万条记录、采样点或内存驻留对象时,整数类型的选择才真正会影响结构体体积和整体占用。这时最合适的做法,通常不是“统一 int64”,而是根据字段职责分别选型。

// 处理大量数据时,选择合适的类型
type DataPoint struct {
    Timestamp int64 // 时间戳用int64
    Value     int32 // 数值范围明确用int32
    Flag      uint8 // 标志位用uint8
}

这个例子里,Timestamp 用 int64 是因为它要表达固定格式的时间值;Value 用 int32,前提是业务确认范围足够;Flag 用 uint8,则是在明确字段很小的情况下节约空间。这样的收益只有在数据规模大时才明显,但一旦规模上来,结构设计是否克制会直接影响内存占用和缓存命中。

几个最常见的坑,最好提前避开

大类型转小类型,可能直接溢出

从宽类型转换到窄类型时,风险一直都在,Go 也不会自动替你兜底。

Go 整型常见风险提示图,集中展示溢出、32 位限制和 JSON 精度问题。
三类风险别等上线后再看真正容易出问题的不是写成 int 还是 int64。
var big int64 = 1234567890123
var small int8 = int8(big) // 溢出!结果不可预期
fmt.Println(small) // 输出什么?不确定!

这类问题常见于数据库字段缩小、协议字段压缩、结构体重构之后的强制转换。处理方法也很简单:转换之前先检查范围,别把“能编译”当作“没风险”。如果字段确实可能超界,就不要为了省空间而改用更小的类型。

int 在 32 位系统上不是无限安全

虽然今天大多数服务端都部署在 64 位系统上,但只要代码存在跨平台运行的可能,int 的平台相关特性就必须纳入考虑。

// 32位系统上,int最大是2147483647
var count int = 2147483647
count++ // 32位系统上会溢出!

如果你的计数值、累计量、业务编号有机会超过 2147483647,就不要继续依赖 int。这种场景里,直接换成 int64 才是更明确的表达。

JSON 里的 int64,还要留意前端精度

int64 在 Go 里没问题,不代表它到了 JSON 和 JavaScript 里也一定安全。只要数值超过 2^53 - 1,也就是约 9007 万亿,JavaScript 的 Number 就可能无法精确表示。

// 这种情况JavaScript可能会丢失精度(数值超过9007万亿时)
type User struct {
    ID int64 `json:"id"`
}

// 解决方法:用string传输
type User struct {
    ID int64  `json:"-"`
    IDStr string `json:"id"`
}

这也是为什么很多后端服务即使数据库字段是 BIGINT,在对外接口里仍会把 ID 作为字符串返回。这里的问题不在 Go,而在消费端的数值表示能力。如果你的接口要给浏览器、Node.js 或其他 JavaScript 环境使用,这一步需要提前确认。

一套够用的选择建议

如果不想每次都从头判断,可以直接按下面这套规则落地:

场景 推荐类型 理由
数组索引、循环计数器 int 与标准库一致,写法自然
普通业务数值(用户年龄、分数等) int 范围通常足够,使用方便
数据库 ID、主键 int64 跨平台一致,避免范围隐患
时间戳 int64 标准接口就是固定宽度
跨网络传输的数值 int64 便于协议和存储保持一致
可能超过 21 亿的数值 int64 避免 32 位环境下溢出
范围很小且规模很大的字段 uint8/int8 可节省内存,但别过度优化

把这张表再压缩成一句话,其实就是:

  • 默认写业务代码,用 int
  • 数据库、时间戳、跨平台数据,用 int64
  • 只有在范围明确且收益明显时,才下探到 int8、uint8、int32 这类具体类型

Go 的类型选择并不鼓励炫技,它更强调场景和表达是否匹配。能让调用方少做转换、能让字段语义更清楚、能让跨边界的数据更稳定,这样的类型选择通常就是对的。放到日常工程里,最实用的结论也很简单:绝大多数局部计算用 int,需要固定宽度时再用 int64。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。