为什么%T不打印常量的类型?

时间:2018-06-20 06:06:41

标签: go types constants

我只是使用官方的旅游/教程来学习golang。在其中一个示例中,我看到一个注释,上面写着An untyped constant takes the type needed by its context.

我正在尝试:

package main

import "fmt"

const (
    // Create a huge number by shifting a 1 bit left 100 places.
    // In other words, the binary number that is 1 followed by 100 zeroes.
    Big = 1 << 100
)

func main() {
    fmt.Printf("Big is of type %T\n", Big)
}

但这在我运行时失败了,

# command-line-arguments
./compile63.go:12:13: constant 1267650600228229401496703205376 overflows int

为什么我不能以这种方式发现常量的类型? (请注意,我是一个新手,很可能还没有对这种语言有足够的了解,无法自己解决这个问题。)

2 个答案:

答案 0 :(得分:5)

  

func Printf

func Printf(format string, a ...interface{}) (n int, err error)
     

Printf根据格式说明符格式化并写入标准   输出。它返回已写入的字节数和任何写入错误   


  

The Go Programming Language Specification


  

Variable declarations

     

变量声明创建一个或多个变量,并进行绑定   相应的标识符,并为每个标识符提供一个类型和一个   初始值。

     

如果给出了表达式列表,则变量将使用进行初始化   遵循分配规则的表达式。否则,每个   变量被初始化为其零值。

     

如果存在类型,则为每个变量指定该类型。除此以外,   给每个变量相应的初始化类型   赋值。如果该值是无类型常量,则为   首先转换为其默认类型;如果它是无类型的布尔值   值,首先将其转换为bool类型。预设值nil   不能用于初始化没有显式类型的变量。


  

Constants

     

常量可以是键入的,也可以是未键入的。文字常量,true,false,   iota和某些仅包含未类型化的常量表达式   常量操作数是无类型的。

     

常量可以通过常量声明或   转换,或在变量声明或   赋值或作为表达式中的操作数。如果   常数值不能表示为各自的值   类型。

     

无类型的常量具有默认类型,即默认类型   在类型值是的上下文中隐式转换常量   例如在简短的变量声明(例如i:= 0)中是必需的   没有显式类型的地方。无类型的默认类型   常量是bool,符文,int,float64,complex128或字符串   分别取决于它是布尔值,符文,整数,   浮点数,复数或字符串常量。


  

Numeric types

     

数字类型表示整数或浮点值的集合。   一些预先声明的与体系结构无关的数字类型:

int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
     

n位整数的值是n位宽,并使用表示   二进制补码算法。

     

还有一些预先声明的数字类型   特定于实现的大小:

uint     either 32 or 64 bits
int      same size as uint

Big是无类型的常量。没有发现的类型。在变量或赋值中使用时,为其指定类型。无类型常量Big的默认类型为int

const Big = 1 << 100

在Go中,所有参数都按值传递,就像通过赋值一样。对于fmt.Printf,第二个参数的类型为interface{}。因此,等效地,

var arg2 interface{} = Big  // constant 1267650600228229401496703205376 overflows int
fmt.Printf("Big is of type %T\n", arg2)

无类型整数常量的默认类型为int。溢出是编译时错误。


例如,

package main

import "fmt"

const (
    // Create a huge number by shifting a 1 bit left 100 places.
    // In other words, the binary number that is 1 followed by 100 zeroes.
    Big = 1 << 100
)

func main() {
    var arg2 interface{} = Big
    fmt.Printf("Big is of type %T\n", arg2)

    fmt.Printf("Big is of type %T\n", Big)
}

游乐场:https://play.golang.org/p/9tynPTek3wN

输出:

prog.go:12:6: constant 1267650600228229401496703205376 overflows int
prog.go:15:13: constant 1267650600228229401496703205376 overflows int

参考:The Go Blog: Constants

答案 1 :(得分:3)

虽然无类型常量确实是其上下文所需的类型,但是它可以假定的类型受语言原语的限制,因此,由于代码常量的存在,在代码中的任何地方实际上都无法使用大的常量。即使在uint64中也不适合的事实。它唯一可能的用途是在另一个常量表达式中使用它,否则将始终引发该错误。

请注意,在Printf(和类似的函数)中,该常量将转换为interface{},因此默认情况下其类型为int。对于32位计算机,如果您的常量表达式溢出int32,则需要首先进行类型转换。

const i = 1 << 50
fmt.Println(i) // => constant 1125899906842624 overflows int
fmt.Println(int64(i)) // => 1125899906842624

如果您想对任意大数进行适当的算术运算,则有一个方便的软件包:math/big

i := big.NewInt(1)
i.Lsh(i, 100)
fmt.Println(i.String())

Playground