golang 里面为什么要设计 int 这样一个数据类型? - V2EX
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Advertisement
AutumnVerse

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

  •  
  •   AutumnVerse Jan 14, 2021 5987 views
    This topic created in 1944 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

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

    grpc 就果断抛弃了 int
    AutumnVerse
        16
    AutumnVerse  
    OP
       Jan 15, 2021
    @secondwtq 多谢大佬解释
    INCerry
        17
    INCerry  
       Jan 15, 2021
    那你可以用 C# C#在 64 位或者 32 位系统中 int 都是 Int32
    binlearn
        18
    binlearn  
       Jan 15, 2021
    如果我没有猜错,这应该是不同平台“字节对齐”的原因。用 int 能保证字节对齐
    coolesting
        19
    coolesting  
       Jan 15, 2021 via Android
    类型细分化,按需分配内存,工作更效率,和 rust 的设计同出一策,所以这两门语言在未来肯定会称霸一方。
    About     Help     Advertise     Blog     API     FAQ     Solana     5701 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 88ms UTC 03:31 PVG 11:31 LAX 20:31 JFK 23:31
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86