忘了在哪本书上看到的例子:
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 语言存在隐式类型转换了。
有请知道的大佬解答原因,还有没有类似的情况呢?
1
lysShub 115 天前
1.5e3 只是一种写法,有小数点不一定是浮点数啊,试试 var b int = 1.55555e3
|
2
MoYi123 115 天前
1.5e3 这是个字面量, 编译的时候会根据上下文推一个类型出来, 如果推不出来就是 float.
|
3
assassing OP @lysShub 官方提到指数形式用于表达浮点数,但并没有用于整型的示例,我很迷惑: https://go.dev/ref/spec#Floating-point_literals
|
4
qq316107934 115 天前
是的,你可以试试把 1.5e3 改成 1.5555e3 ,会报错:cannot use 1.5555e3(untyped float constant 1555.55) as int value in variable declaration 表明存在编译类型转换
|
5
assassing OP @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`?不知道怎么理解 |
6
thinkershare 115 天前
@assassing 要记住,go 的常量没有类型,类型是在使用它的时候确定的。
|
7
qq316107934 115 天前
|
8
assassing OP @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` 也是能通过编译的。只是差一个官方说明,说好了必须要显式转换类型呢? |
9
eaglexiang 115 天前
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. |
10
kuro1 115 天前
可以试试
``` func main() { const a = 5 fmt.Printf("%v", a*math.Pi) } ``` |
11
thinkershare 115 天前 1
编译器会放松对 untyped 类型的赋值检查。你给出的示例,n 是 untyped int, d 是 untyped float ,但你用参数传递时,它必须要是一个确定类型,此时 untyped float 被推断为默认的浮点类型 float64 ,untyped 的 int 会被推断为 int
|
12
qq316107934 115 天前 1
https://go.dev/ref/spec#Variable_declarations
If that value is an untyped constant, it is * first implicitly converted to its default type* ; if it is an untyped boolean value, it is first implicitly converted to type bool. 官方对无类型常量还是有说明的 |
13
assassing OP @qq316107934 谢谢提供信息,编译器源码我还不太看得懂,先把问题记下来了
|
14
xuld 115 天前 1
文档一般是滞后的,不要试图对文档或其他概念咬文嚼字,这是中国人常犯的错误:不必在乎概念或文字上的差异,不必在乎“是否存在隐式类型转换”,是又怎样,不是又怎样。
go 语言设计之初为了简单,决定不加入隐式类型转换。 多数情况这个决定没有问题,但有一个例外,就是楼主所发现的问题,原本在 C 语言里,因为存在隐式类型转换,这么写毫无违和感。但 Go 现在没隐式类型转换了,这样写会不会报错? 所以最终的结论是看作者要不要对这个场景特殊处理。至于它到底是不是隐式类型转换,连作者都不在乎。他只知道这种写法有可能用到,编译器应该能处理。 |
15
assassing OP @thinkershare 作为常量是可以解释得通,那么下次看到 e 还得心算一下,结果是不是个小数
|
17
rrfeng 115 天前 via Android
字面量类型比较灵活。
|
19
nagisaushio 115 天前 via Android
@assassing 字面常量是**任意精度**的数,没有浮点与否之分。当字面常量赋给有类型变量时,会根据该类型的约束作检查(范围?是否支持小数?)并决定是否报错
|
20
nagisaushio 115 天前 via Android
|
21
xuld 115 天前
@nagisaushio 你在偷换概念。
细读 go spec 和咬文嚼字是一个意思吗? 细读西游记 = 了解每个故事情节、掌握所有人物剧情、分析不同人的行为。 对西游记咬文嚼字 = 为什么唐僧从出发到西天取经,一路上吃的都是东方的食物,一点西方的食物都没有。 |
22
vx7298 115 天前
var i int=10.0
var i int=10.2 |
23
assassing OP |