各位大佬,在 go 中一个 const 声明超出 uint64 最大值后这个数的类型是什么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
nevermoreluo
V2EX    Go 编程语言

各位大佬,在 go 中一个 const 声明超出 uint64 最大值后这个数的类型是什么?

  •  
  •   nevermoreluo 2024-07-23 09:59:23 +08:00 2933 次点击
    这是一个创建于 519 天前的主题,其中的信息可能已经有所发展或是发生改变。

    初学 go ,看教程 const的时候,发现 Big = 1 << 100 明显超出基础类型 uint64 了,于是想看下 Big 是什么类型

    但是打印都 overflow 了遂有此疑问

     const ( // 将 1 左移 100 位来创建一个非常大的数字 // 即这个数的二进制是 1 后面跟着 100 个 0 Big = 1 << 100 // 再往右移 99 位,即 Small = 1 << 1 ,或者说 Small = 2 Small = Big >> 99 ) func main() { // cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to fmt.Printf (overflows) fmt.Printf("T of Big %T\n", Big) // cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to reflect.TypeOf (overflows) fmt.Println("T of Big ", reflect.TypeOf(Big)) } 
    第 1 条附言    2024-07-23 11:15:11 +08:00

    可能是我的问题提问的方式不对,我有疑问的原因是,理所当然的认为const没有声明go又是强类型应该和cpp的auto一样,在编译时推断Big的类型,在运行时处理。所以才会问这个Big在运行时的类型问题。

    不过anyway,可以结帖了。

    TLDR;
    go在编译时直接处理了值,如果这些untyped value需要运行时执行并且无法满足默认类型时会报错。

    所以go可以在编译时这些值可以被精确的计算出Small的值, 但是运行时打印Big会被当成int从而overflow报错。

    楼里提到的相关资料:
    https://stackoverflow.com/questions/38982278/how-does-go-perform-arithmetic-on-constants/38982889#38982889

    https://go.dev/blog/constants

    https://www.ardanlabs.com/blog/2014/04/introduction-to-numeric-constants-in-go.html

    但是这样又开始了一个迷思,为什么他可以处理这些数,go对于这个精确的值处理范围有极限嘛? 可能有空了要再去探索下。

    16 条回复    2024-07-24 00:36:01 +08:00
    uiosun
        1
    uiosun  
       2024-07-23 10:03:27 +08:00
    dapang1221
        2
    dapang1221  
       2024-07-23 10:11:43 +08:00
    鉴定为计算机原理没学好,重新看下书
    nevermoreluo
        3
    nevermoreluo  
    OP
       2024-07-23 10:16:30 +08:00
    @uiosun
    这篇我看了 但是还是没搞明白这个 Big 到底属于什么类型。
    或者说我的问题应该改为
    对于 go 来说他既然可以运算 Small 的值,那么在运行时他拿什么类型处理 Big 这个超出他规定基础类型的对象的?
    pkoukk
        4
    pkoukk  
       2024-07-23 10:17:28 +08:00
    你没声明它的类型它哪来的类型?
    aminobody
        5
    aminobody  
       2024-07-23 10:21:31 +08:00
    @nevermoreluo #3 `The default type for the untyped constant Big is int.`
    nevermoreluo
        6
    nevermoreluo  
    OP
       2024-07-23 10:28:42 +08:00
    @aminobody 1 << 100 超出 int 的存储范围了
    nevermoreluo
        7
    nevermoreluo  
    OP
       2024-07-23 10:31:58 +08:00
    看到这个
    https://stackoverflow.com/questions/38982278/how-does-go-perform-arithmetic-on-constants/38982889#38982889

    大概理解了,在编译时把这个值处理了,运行时就不用考虑了,所以企图打印他会在编译时报错,但是计算可以。
    谢谢各位大佬
    otakustay
        8
    otakustay  
       2024-07-23 10:32:38 +08:00
    超出范围就溢出呗,溢出又不会改变类型
    zonyitoo
        9
    zonyitoo  
       2024-07-23 10:36:04 +08:00   2
    nevermoreluo
        10
    nevermoreluo  
    OP
       2024-07-23 10:43:22 +08:00
    @zonyitoo
    因为没有声明类型,先入为主的以为跟 c++的 auto 一样编译时推断了。
    看起来这个 const 在 go 里面有很多细节处理,学习了,谢谢大佬。
    lasuar
        11
    lasuar  
       2024-07-23 10:44:05 +08:00
    默认一律是 int 类型,数据溢出按溢出处理,搜索 [编程语言整型溢出] ,
    nevermoreluo
        12
    nevermoreluo  
    OP
       2024-07-23 10:47:25 +08:00
    @lasuar
    应该不是的,他并没有做溢出处理,而是在编译时精确的计算了。
    你可以简单打印以下这几个值看看。如果按他最大基础类型 uint64 算的话,溢出处理,和实际结果不对。

    const Big = 18446744073709551617;
    const OtherBig = Big + 1;
    const BigI = OtherBig - 3;
    lasuar
        13
    lasuar  
       2024-07-23 10:54:42 +08:00
    这里因为是常量方式的声明,所以直接编译失败了。类型默认 INT ,没有如果。
    wudanyang
        14
    wudanyang  
       2024-07-23 10:59:17 +08:00
    编译的时候就出错了,还有啥类型
    uiosun
        15
    uiosun  
       2024-07-23 10:59:40 +08:00
    @nevermoreluo

    这篇问答里的 comment 有更多文章可以阅读,其中以官方文档为例:

    > But in Go, a constant is just a simple, unchanging value, and from here on we’re talking only about Go.

    按我理解,常量只是作为一个值,当你需要推断它的类型时,Go 才会尝试推断它的类型推断。

    所以,你的报错很正常,正是反映了这样的规则:cannot use Big (untyped int constant 1267650600228229401496703205376) as int value in argument to fmt.Printf (overflows)
    wisej
        16
    wisej  
       2024-07-24 00:36:01 +08:00   1
    来回答你 append 里的问题:

    1. Big 常量,底层用的 math/big 包
    2. precision 有极限,golang 自带的 compiler 设的 512bit (不过根据 spec ,integer constants 不小于 256 即可)。1<<511 没问题, 1<<512 就报 overflow 了

    这些答案可以在 src/go/constant/value.go 源码找到
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     998 人在线   最高记录 6679       Select Language
    创意工作者的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 19:07 PVG 03:07 LAX 11:07 JFK 14:07
    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