Golang Go语言中为什么要设计int这样一个数据类型?

发布于 1周前 作者 zlyuanteng 来自 Go语言

Golang Go语言中为什么要设计int这样一个数据类型?

在 golang 里面,有 int64,int32,int 这 3 种数据类型。

int64: 占 64 位的整数数据类型

int32: 占 32 位的整数数据类型

int: 在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位

于是我就纳闷了,int 这个数据类型不是埋坑吗?不同的处理器上面可能导致不同的运行结果,那设计这个数据类型的意义是啥呢?为啥不只保留 int64 和 int32,由程序员指定长度,保证运行结果的一致性

我 google 查了很久,没找到相关的资料,还望了解的老哥赐教


更多关于Golang Go语言中为什么要设计int这样一个数据类型?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

20 回复

因为程序员往往不能预知他写的代码会在什么环境下运行……

更多关于Golang Go语言中为什么要设计int这样一个数据类型?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


老哥没见过 C 语言里的 int, int32_t, int64_t ?

#1 就因为不能预知,所有指定使用 int64 或者 int32 不更加保险吗

有一个可能性是为了效率,在 64 位上为了 int32 需要 runtime 手动限制只使用低 32 位,可能需要手动调整溢出 flag ?
32 位上 int64 是必然需要模拟的……

在不 care 最大值的时候使用 int, 让所有的 CPU 都开心.

如果说你肯定该数远远达不到 int32 和 int64 (比如一个 flag,只能取 012,其他均视为未定义行为),那么这个 overhead 就比较明显了。
而如果你有一百万个这样的数……

我也挺纳闷的

int 跟机器字长一致,这样可以获取最大的执行效率。在不关心数值范围的场景下 int 足够了,比如数组下标。相反如果你在 32 位机器上使用 int64,本来一条指令的事情要变成多条指令。
int32 和 int64 这些一般用于编解码、底层硬件相关,或者是数值范围敏感的场景。

如果你指定 x64,在 x86 平台上就跑不起来啦。指定 x86,x64 平台倒是能跑,但性能就浪费了。

我的理解相反,int 是平台原生,int32 int64 才是有意设计的

在 golang 里面,有 int64,int32,int 这 3 种数据类型。
int64: 占 64 位的整数数据类型

int32: 占 32 位的整数数据类型

int: 在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位

在 c/c++ 里面,有 long long int,int,long int 这 3 种数据类型。
long long int: 占 64 位的整数数据类型

int: 占 32 位的整数数据类型(32 位及 64 位平台,8 位和 16 位不考虑了)

long int: 在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位

实际上,在不需要做存储和通讯协议数据对齐的场景下,long int 是在跨平台情况下效率最高的。
跨平台存储和通讯协议数据对齐场景下,4 字节就固定 int32,8 字节就固定 int64

看到 C99/C++11 的这些,你会更纳闷的
en.cppreference.com/w/c/types/integer
其实原因很简单,就是为了执行效率,一些情况下,我们并不关心 int 到底是 32 位还是 64 位的,反正都够用,这时候就没必要强制指定位数,而是让编译器自己去自行选择效率最高的位数

仅就 x86 而言,int64 还真不一定比 int32 快
“快不快”不仅仅是指令支持的问题,数据宽了一倍,占用的缓存空间、内存带宽都加了一倍。如果真有一百万个这样的数,可能还真是 32 位好一点,特别再考虑到 SIMD 的情况下

如果这货的行为真的像楼主说的一样“在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位”的话,那么看 C/C++ 是正解,不过鉴于大道至简的 Go 目标之一就是干死 C++,估计没人会去看的。

C 里面有一个类型叫 size_t,相当于 Go 的 uint,还有个 ptrdiff_t,相当于 Go 里的 int (假设楼主说的行为是对的)
size_t 顾名思义,可以装下任何对象的“大小”,比如在 32 位环境下,地址空间中不可能存在多于 2^32 个唯一的对象,一个对象的大小也不可能超过 2^32 字节,所以 size_t 做成 uint32_t 就可以。需要存大小、数量时就用这货。
ptrdiff_t 顾名思义,可以装下任意两个指针相减的结果,需要存偏移时就用这货。(不过 C 标准里面貌似没有保证,毕竟真正存差值需要 wordsize+1 位 …)
毕竟如果是 32 位环境,用 64 位数存数组有多少个元素实在太过奢侈了,这时候根据大道至简的原则,就可以加一个类型叫 int 。

这只是一个猜想,因为 Go 的所谓 spec 实在太大道至简了:
> uint either 32 or 64 bits
> int same size as uint
反正在这两句话我是没找着“在 64 位处理器上占 64 位,在 32 位处理器上面占 32 位”的保证。因为他把这玩意写在后面 builtin functions 部分了:“The built-in functions len and cap take arguments of various types and return a result of type int. The implementation guarantees that the result always fits into an int.”,然后就有了这个 https://yourbasic.org/golang/int-vs-int64/ 。也就是说这个类型和它的角色并不直接关联,可能本来设计者的想法就是从 C 里面随便捣鼓来的 …

噢对了补充下,我知道做优化的时候有至少一种情况会把 32 位数故意 widen 成 64 位,就是频繁转换的时候。
具体来说,是一个循环的 induction variable ( https://en.wikipedia.org/wiki/Induction_variable )被定义为 32 位,但是使用时总是先 cast 成 64 位再使用,这种情况用 64 位数代替原来的 induction variable 可以省去转换的开销,并且就一两个变量一般都放寄存器里面,做起来才值得。
(嘛不过我只是观察到这么一种行为,并没有找到对应的参考,也没有仔细看相关的代码 …)

自 2008 年 1 月起,Ken Thompson 就开始研发一款以 C 语言为目标结果的编译器来拓展 Go 语言的设计思想。

c 有 go 就有了,因为顺手~

grpc 就果断抛弃了 int

多谢大佬解释

那你可以用 C# C#在 64 位或者 32 位系统中 int 都是 Int32

如果我没有猜错,这应该是不同平台“字节对齐”的原因。用 int 能保证字节对齐

类型细分化,按需分配内存,工作更效率,和 rust 的设计同出一策,所以这两门语言在未来肯定会称霸一方。

在Golang(Go语言)中,设计int这样一个数据类型是出于多种考虑,这些考虑涵盖了编程的通用性、性能以及语言的简洁性。

首先,int是整数类型的基础,它提供了一种直接且高效的方式来存储没有小数部分的数值。在大多数编程场景中,整数都是不可或缺的数据类型,用于计数、索引、循环控制等。

其次,Go语言的int类型具有平台相关性,这意味着在不同的硬件和操作系统上,int的大小(位数)可能会有所不同。这种设计使得Go程序能够在不同的平台上高效运行,因为int的大小可以自然地适应目标平台的内存和性能特性。

此外,Go语言的设计哲学强调简洁性和明确性。通过提供int这一通用整数类型,Go语言减少了程序员需要记忆和处理的整数类型数量,从而降低了编程的复杂性。

最后,int类型还与其他Go语言特性(如类型转换、常量折叠等)紧密集成,使得整数运算在Go中既安全又高效。

综上所述,Go语言设计int数据类型是为了提供一种通用、高效且简洁的整数表示方式,以适应不同的编程需求和平台特性。这种设计使得Go语言在整数处理方面既灵活又强大,是Go语言成功的重要因素之一。

回到顶部