V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
jiangwei2222
V2EX  ›  Go 编程语言

golang 里面为什么要设计 int 这样一个数据类型?

  •  
  •   jiangwei2222 · 2021-01-14 15:23:28 +08:00 · 4883 次点击
    这是一个创建于 1169 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

    19 条回复    2021-01-15 20:49:27 +08:00
    xuanbg
        1
    xuanbg  
       2021-01-14 15:27:25 +08:00
    因为程序员往往不能预知他写的代码会在什么环境下运行……
    wudicgi
        2
    wudicgi  
       2021-01-14 15:30:01 +08:00
    老哥没见过 C 语言里的 int, int32_t, int64_t ?
    jiangwei2222
        3
    jiangwei2222  
    OP
       2021-01-14 15:31:32 +08:00
    @xuanbg #1 就因为不能预知,所有指定使用 int64 或者 int32 不更加保险吗
    no1xsyzy
        4
    no1xsyzy  
       2021-01-14 15:33:22 +08:00
    有一个可能性是为了效率,在 64 位上为了 int32 需要 runtime 手动限制只使用低 32 位,可能需要手动调整溢出 flag ?
    32 位上 int64 是必然需要模拟的……
    ruyu
        5
    ruyu  
       2021-01-14 15:35:32 +08:00   ❤️ 2
    在不 care 最大值的时候使用 int, 让所有的 CPU 都开心.
    no1xsyzy
        6
    no1xsyzy  
       2021-01-14 15:36:01 +08:00
    如果说你肯定该数远远达不到 int32 和 int64 (比如一个 flag,只能取 012,其他均视为未定义行为),那么这个 overhead 就比较明显了。
    而如果你有一百万个这样的数……
    zoharSoul
        7
    zoharSoul  
       2021-01-14 15:36:56 +08:00
    我也挺纳闷的
    icexin
        8
    icexin  
       2021-01-14 15:38:43 +08:00   ❤️ 3
    int 跟机器字长一致,这样可以获取最大的执行效率。在不关心数值范围的场景下 int 足够了,比如数组下标。相反如果你在 32 位机器上使用 int64,本来一条指令的事情要变成多条指令。
    int32 和 int64 这些一般用于编解码、底层硬件相关,或者是数值范围敏感的场景。
    xuanbg
        9
    xuanbg  
       2021-01-14 15:41:33 +08:00
    @jiangwei2222 如果你指定 x64,在 x86 平台上就跑不起来啦。指定 x86,x64 平台倒是能跑,但性能就浪费了。
    eason1874
        10
    eason1874  
       2021-01-14 15:49:26 +08:00   ❤️ 1
    我的理解相反,int 是平台原生,int32 int64 才是有意设计的
    LANB0
        11
    LANB0  
       2021-01-14 16:06:00 +08:00
    在 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
    teawithlife
        12
    teawithlife  
       2021-01-14 16:14:37 +08:00
    看到 C99/C++11 的这些,你会更纳闷的
    en.cppreference.com/w/c/types/integer
    其实原因很简单,就是为了执行效率,一些情况下,我们并不关心 int 到底是 32 位还是 64 位的,反正都够用,这时候就没必要强制指定位数,而是让编译器自己去自行选择效率最高的位数
    secondwtq
        13
    secondwtq  
       2021-01-14 20:55:38 +08:00   ❤️ 2
    仅就 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 里面随便捣鼓来的 ...
    secondwtq
        14
    secondwtq  
       2021-01-14 21:10:42 +08:00
    噢对了补充下,我知道做优化的时候有至少一种情况会把 32 位数故意 widen 成 64 位,就是频繁转换的时候。
    具体来说,是一个循环的 induction variable ( https://en.wikipedia.org/wiki/Induction_variable )被定义为 32 位,但是使用时总是先 cast 成 64 位再使用,这种情况用 64 位数代替原来的 induction variable 可以省去转换的开销,并且就一两个变量一般都放寄存器里面,做起来才值得。
    (嘛不过我只是观察到这么一种行为,并没有找到对应的参考,也没有仔细看相关的代码 ...)
    douyacun
        15
    douyacun  
       2021-01-14 22:43:26 +08:00
    自 2008 年 1 月起,Ken Thompson 就开始研发一款以 C 语言为目标结果的编译器来拓展 Go 语言的设计思想。

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

    grpc 就果断抛弃了 int
    jiangwei2222
        16
    jiangwei2222  
    OP
       2021-01-15 11:02:04 +08:00
    @secondwtq 多谢大佬解释
    INCerry
        17
    INCerry  
       2021-01-15 13:45:22 +08:00
    那你可以用 C# C#在 64 位或者 32 位系统中 int 都是 Int32
    binlearn
        18
    binlearn  
       2021-01-15 13:58:56 +08:00
    如果我没有猜错,这应该是不同平台“字节对齐”的原因。用 int 能保证字节对齐
    coolesting
        19
    coolesting  
       2021-01-15 20:49:27 +08:00 via Android
    类型细分化,按需分配内存,工作更效率,和 rust 的设计同出一策,所以这两门语言在未来肯定会称霸一方。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   984 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:30 · PVG 04:30 · LAX 13:30 · JFK 16:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.