为什么这段代码不能编译?
package main
const a = 1.000001
const base = 0
const b = a+base
func main() {
f(b)
}
func f(int) {}
$ go run a.go
# command-line-arguments
./a.go:4: constant 1 truncated to integer
它是说1被截断了?或者说1不能被截断?它说的是哪一个?
有人回答说上面的代码不能编译,因为b
是一个float64
。但是为什么会这样编译呢:
package main
import "fmt"
const a = 1.000001
const b = a-0.000001
func main() {
fmt.Printf("%T %v\n",a,a)
fmt.Printf("%T %v\n",b,b)
f(b)
}
func f(int) {}
$ go run a.go
float64 1.000001
float64 1
?b
在这里是一个float64
,但它可以传递给f
。
发布于 2014-08-31 01:03:07
go团队最近做了一个blog post about this,我建议你读一读。
从引言
Go是一种静态类型语言,不允许混合数字类型的操作。不能将float64添加到int,甚至不能将int32添加到int。然而,编写1e6*time.Second或math.Exp(1)甚至1<<('\t'+2.0)是合法的。在Go中,常量与变量不同,其行为与常规数字非常相似。这篇文章解释了为什么会这样,以及它的含义。
TLDR -常量在Go中是无类型的。他们的类型只是在最后一刻才被具体化。
这就解释了你上面的问题。给定的
func f(int) {}
然后
f(1) // ok
f(1.000) // OK
f(1.0E6) // OK
f(1.0001) // BAD
发布于 2014-08-31 01:07:34
Go有常量的very strict conversion rules:
在以下任何情况下,常量值x都可以转换为类型T:
x
可由T
.x
类型的值表示,T是浮点类型,x可由使用IEEE754四舍五入规则舍入后的T
类型的值表示。常量value.x
是整数常量,T
是字符串类型,常量是四舍五入的T(x)
。与非常数x
相同的规则也适用于这种情况。golang blog post about constants可能有助于进一步理解这一点。由于严格性,每个违反引用规则的转换都被认为是错误的。这背后的原因是Go试图尽可能准确地表示常量。这也意味着最终的类型是在所使用的表达式的上下文中决定的。抛开精确度,这是一个可能的编程错误的标志。
如果您确实希望将值四舍五入为整数,请将其转换为变量(Example on play):
const b = 1.01
c := b
f(int(c))
这是因为编译器不会跟踪值的来源和不适用于变量的常量规则。
但是为什么当我把它改成这样的时候它还能起作用呢?const a = 1.000001;const b = a-0.000001
在本例中,b
等于1.1。1可以表示为整数,因此不涉及舍入和信息丢失。因此,这不是一个错误,因为它符合浮点值的转换规则(如前所述)。
发布于 2014-09-03 21:21:12
你的第一个程序可以像这样重写:
package main
func main() {
f(1.000001)
}
func f(int) {}
它显然没有将整数值传递给整数函数。
您的第二个程序可以类似地重写如下:
package main
import "fmt"
func main() {
fmt.Printf("%T %v\n",1.000001,1.000001)
fmt.Printf("%T %v\n",1,1)
f(1)
}
func f(int) {}
看起来挺好的。
我所做的就是手动替换a
和b
常量。这就是go所做的一切。
https://stackoverflow.com/questions/25584329
复制相似问题