初学 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))
}
可能是我的问题提问的方式不对,我有疑问的原因是,理所当然的认为const没有声明go又是强类型应该和cpp的auto一样,在编译时推断Big的类型,在运行时处理。所以才会问这个Big在运行时的类型问题。
不过anyway,可以结帖了。
TLDR;
go在编译时直接处理了值,如果这些untyped value需要运行时执行并且无法满足默认类型时会报错。
所以go可以在编译时这些值可以被精确的计算出Small的值, 但是运行时打印Big会被当成int从而overflow报错。
https://www.ardanlabs.com/blog/2014/04/introduction-to-numeric-constants-in-go.html
但是这样又开始了一个迷思,为什么他可以处理这些数,go对于这个精确的值处理范围有极限嘛? 可能有空了要再去探索下。
![]() |
1
uiosun 46 天前
|
![]() |
2
dapang1221 46 天前
鉴定为计算机原理没学好,重新看下书
|
3
nevermoreluo OP @uiosun
这篇我看了 但是还是没搞明白这个 Big 到底属于什么类型。 或者说我的问题应该改为 对于 go 来说他既然可以运算 Small 的值,那么在运行时他拿什么类型处理 Big 这个超出他规定基础类型的对象的? |
![]() |
4
pkoukk 46 天前
你没声明它的类型它哪来的类型?
|
![]() |
5
aminobody 46 天前
@nevermoreluo #3 `The default type for the untyped constant Big is int.`
|
6
nevermoreluo OP @aminobody 1 << 100 超出 int 的存储范围了
|
7
nevermoreluo OP 看到这个
https://stackoverflow.com/questions/38982278/how-does-go-perform-arithmetic-on-constants/38982889#38982889 大概理解了,在编译时把这个值处理了,运行时就不用考虑了,所以企图打印他会在编译时报错,但是计算可以。 谢谢各位大佬 |
![]() |
8
otakustay 46 天前
超出范围就溢出呗,溢出又不会改变类型
|
![]() |
9
zonyitoo 46 天前 ![]() https://www.ardanlabs.com/blog/2014/04/introduction-to-numeric-constants-in-go.html
因为你的 Big 并没有指定类型,所以它是 kind: integer 。 https://go.dev/ref/spec#Constant_expressions |
10
nevermoreluo OP |
![]() |
11
lasuar 46 天前
默认一律是 int 类型,数据溢出按溢出处理,搜索 [编程语言整型溢出] ,
|
12
nevermoreluo OP @lasuar
应该不是的,他并没有做溢出处理,而是在编译时精确的计算了。 你可以简单打印以下这几个值看看。如果按他最大基础类型 uint64 算的话,溢出处理,和实际结果不对。 const Big = 18446744073709551617; const OtherBig = Big + 1; const BigI = OtherBig - 3; |
![]() |
13
lasuar 46 天前
这里因为是常量方式的声明,所以直接编译失败了。类型默认 INT ,没有如果。
|
![]() |
14
wudanyang 46 天前
编译的时候就出错了,还有啥类型
|
![]() |
15
uiosun 46 天前
@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) |
![]() |
16
wisej 46 天前 ![]() 来回答你 append 里的问题:
1. Big 常量,底层用的 math/big 包 2. precision 有极限,golang 自带的 compiler 设的 512bit (不过根据 spec ,integer constants 不小于 256 即可)。1<<511 没问题, 1<<512 就报 overflow 了 这些答案可以在 src/go/constant/value.go 源码找到 |