Go 语言存在隐式类型转换? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
assassing
V2EX    程序员

Go 语言存在隐式类型转换?

  •  
  •   assassing
    hxz393 2024-07-29 16:50:47 +08:00 2714 次点击
    这是一个创建于 490 天前的主题,其中的信息可能已经有所发展或是发生改变。

    忘了在哪本书上看到的例子:

    package main import "fmt" func main() { // 不指定类型时为浮点数 var a = 2e3 fmt.Printf("%T: %v\n", a, a) // 输出:float64: 2000 // 编译成功,因为 1.5e3 等于 1500 ,是一个整数 var b int = 1.5e3 fmt.Printf("%T: %v\n", b, b) // 输出:int: 1500 } 

    上面代码中,为什么 var b int = 1.5e3 能通过编译,难道科学计数法被视为算术表达式或常量表达式?不然我只能认为 Go 语言存在隐式类型转换了。

    有请知道的大佬解答原因,还有没有类似的情况呢?

    23 条回复    2024-07-29 20:22:52 +08:00
    lysShub
        1
    lysShub  
       2024-07-29 16:54:23 +08:00
    1.5e3 只是一种写法,有小数点不一定是浮点数啊,试试 var b int = 1.55555e3
    MoYi123
        2
    MoYi123  
       2024-07-29 17:13:09 +08:00
    1.5e3 这是个字面量, 编译的时候会根据上下文推一个类型出来, 如果推不出来就是 float.
    assassing
        3
    assassing  
    OP
       2024-07-29 17:14:06 +08:00
    @lysShub 官方提到指数形式用于表达浮点数,但并没有用于整型的示例,我很迷惑: https://go.dev/ref/spec#Floating-point_literals
    qq316107934
        4
    qq316107934  
       2024-07-29 17:29:36 +08:00
    是的,你可以试试把 1.5e3 改成 1.5555e3 ,会报错:cannot use 1.5555e3(untyped float constant 1555.55) as int value in variable declaration 表明存在编译类型转换
    assassing
        5
    assassing  
    OP
       2024-07-29 17:32:42 +08:00
    @MoYi123 我也偏向于认为 1.5e3 是个字面量,应该说默认推断类型就是 float64:

    ```
    package main

    import (
    "fmt"
    )

    func main() {
    const n = 5000000

    const d = 3e6 + n
    fmt.Println(d) // 输出:8e+06
    fmt.Printf("%T\n", d) // 输出:float64
    }
    ```
    所以和无类型常量计算结果也是 float64 。
    然后把指数形式的浮点数赋值给整数:`var b int = 1.5555e3`,编译器报错信息是:`constant 1555.5 truncated to integer`?不知道怎么理解
    thinkershare
       
    thinkershare  
       2024-07-29 17:33:17 +08:00
    @assassing 要记住,go 的常量没有类型,类型是在使用它的时候确定的。
    assassing
        8
    assassing  
    OP
       2024-07-29 17:37:02 +08:00
    @qq316107934 换了 1.22 版本报错就是这个:`cannot use 1.5555e3 (untyped float constant 1555.5) as int value in variable declaration (truncated)`
    我试了 1.5 版本,`var b int = 1.5e3` 也是能通过编译的。只是差一个官方说明,说好了必须要显式转换类型呢?
    eaglexiang
        9
    eaglexiang  
       2024-07-29 17:39:08 +08:00
    https://go.dev/ref/spec#Constants

    > A constant may be given a type explicitly by a constant declaration or conversion, or implicitly when used in a variable declaration or an assignment statement or as an operand in an expression.
    kuro1
        10
    kuro1  
       2024-07-29 17:39:25 +08:00
    可以试试
    ```
    func main() {
    const a = 5
    fmt.Printf("%v", a*math.Pi)
    }
    ```
    thinkershare
        11
    thinkershare  
       2024-07-29 17:40:05 +08:00   1
    编译器会放松对 untyped 类型的赋值检查。你给出的示例,n 是 untyped int, d 是 untyped float ,但你用参数传递时,它必须要是一个确定类型,此时 untyped float 被推断为默认的浮点类型 float64 ,untyped 的 int 会被推断为 int
    qq316107934
        12
    qq316107934  
       2024-07-29 17:51:21 +08:00   1
    https://go.dev/ref/spec#Variable_declarations

    If that value is an untyped constant, it is * first implicitly converted to its default type* ; i it is an untyped boolean value, it is first implicitly converted to type bool.

    官方对无类型常量还是有说明的
    assassing
        13
    assassing  
    OP
       2024-07-29 17:54:21 +08:00   1
    @qq316107934 谢谢提供信息,编译器源码我还不太看得懂,先把问题记下来了
    xuld
        14
    xuld  
       2024-07-29 17:57:14 +08:00   1
    文档一般是滞后的,不要试图对文档或其他概念咬文嚼字,这是中国人常犯的错误:不必在乎概念或文字上的差异,不必在乎“是否存在隐式类型转换”,是又怎样,不是又怎样。

    go 语言设计之初为了简单,决定不加入隐式类型转换。

    多数情况这个决定没有问题,但有一个例外,就是楼主所发现的问题,原本在 C 语言里,因为存在隐式类型转换,这么写毫无违和感。但 Go 现在没隐式类型转换了,这样写会不会报错?

    所以最终的结论是看作者要不要对这个场景特殊处理。至于它到底是不是隐式类型转换,连作者都不在乎。他只知道这种写法有可能用到,编译器应该能处理。
    assassing
        15
    assassing  
    OP
       2024-07-29 17:59:41 +08:00
    @thinkershare 作为常量是可以解释得通,那么下次看到 e 还得心算一下,结果是不是个小数
    assassing
        16
    assassing  
    OP
       2024-07-29 18:00:58 +08:00
    @kuro1 math.Pi 是个明确的 float64 ,没有争议
    rrfeng
        17
    rrfeng  
       2024-07-29 18:02:36 +08:00 via Android
    字面量类型比较灵活。
    assassing
        18
    assassing  
    OP
       2024-07-29 18:06:51 +08:00
    @xuld 谢谢忠告,咱只想心里有个底,不然看到指数形式就默认是浮点数了。既然没问题就放心用
    nagisaushio
        19
    nagisaushio  
       2024-07-29 18:14:47 +08:00 via Android
    @assassing 字面常量是**任意精度**的数,没有浮点与否之分。当字面常量赋给有类型变量时,会根据该类型的约束作检查(范围?是否支持小数?)并决定是否报错
    nagisaushio
        20
    nagisaushio  
       2024-07-29 18:18:50 +08:00 via Android
    @xuld > 文档一般是滞后的,不要试图对文档或其他概念咬文嚼字

    go spec 是 go 语义的标准,不是一般的文档,会跟上每个版本变化。细读 go spec 理解语义我觉得是正确的做法
    xuld
        21
    xuld  
       2024-07-29 18:39:13 +08:00
    @nagisaushio 你在偷换概念。

    细读 go spec 和咬文嚼字是一个意思吗?

    细读西游记 = 了解每个故事情节、掌握所有人物剧情、分析不同人的行为。

    对西游记咬文嚼字 = 为什么唐僧从出发到西天取经,一路上吃的都是东方的食物,一点西方的食物都没有。
    vx7298
        22
    vx7298  
       2024-07-29 18:50:45 +08:00
    var i int=10.0
    var i int=10.2
    assassing
        23
    assassing  
    OP
       2024-07-29 20:22:52 +08:00
    @nagisaushio 现在认知是:用指数形式表示的数,是一个不定类型的常量,可能为整数也可能为浮点数。就和下面这种情况一样:

    const c = 1.0
    var d int = c
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1102 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 17:55 PVG 01:55 LAX 09:55 JFK 12:55
    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