userid := 12345
did := (userid & ^(0xFFFF << 48))
编译此代码时,我得到了:
./xxxx.go:511: constant -18446462598732840961 overflows int
你知道这件事有什么关系吗?如何解决? 感谢。
答案 0 :(得分:10)
^(0xFFFF << 48)
是一个无类型的常量,它的值是任意大的值。
0xffff << 48
是0xffff000000000000
。当你否定它时,你得到-0xffff000000000001
(因为有两个补码,-x = ^ x + 1,或^ x = - (x + 1))。
当您撰写userid := 12345
时,userid
会获得int
类型。然后,当您尝试使用无类型常量&
并且(-0xffff000000000001
)时,编译器会发现此常量需要为int
。此时,编译器会抱怨,因为该值太大而不能为int
。
如果你想要获得常量0x0000ffffffffffff
,那么你可以使用1<<48 - 1
,它(如果你有64位整数)将适合。由于如果int
为32位,您的代码将无法运行,那么您应该在代码中使用int64
而不是int
来使其可移植。
博客文章https://blog.golang.org/constants解释了常量的工作原理,以及有关它们原因的一些背景知识。
答案 1 :(得分:2)
The Go Programming Language Specification
数字常量表示任意精度的值,而不是 溢出。
常量可以是键入的或无类型的。
常量可以通过常量声明明确地给出一个类型 转换,或在变量声明或。中使用时隐式转换 赋值或作为表达式中的操作数。如果这是一个错误 常数值不能表示为各自的值 类型。
非类型化常量具有默认类型,该类型是 在类型值为的上下文中隐式转换常量 例如,在一个简短的变量声明中,例如i:= 0 没有明确类型的地方。无类型的默认类型 常量是bool,rune,int,float64,complex128或string 分别取决于它是否是布尔值,符文,整数, 浮点,复数或字符串常量。
int
是特定于实现的大小,32位或64位。
userid
的类型为int
。例如,
package main
import "fmt"
func main() {
userid := 12345
did := uint64(userid) & ^uint64(0xFFFF<<48)
fmt.Println(userid, did)
}
输出:
12345 12345