理论上int64适合uint64,当然它们的数值会有所不同,因为int64上的第一个位是为符号保留的,但是为什么我不能做这个转换?这对我来说似乎是有效的
import (
"fmt"
"math"
)
func main() {
var randomNum uint64 = math.MinInt64
fmt.Println(randomNum)
}
收益率错误
constant -9223372036854775808 overflows uint64
这里的math.MinInt64
是-9223372036854775808
,技术上是一个63位加号的数字。
我主要研究这个,因为我想将8 bytes
转换回具有适当符号的int64,但到目前为止,我只看到返回uint64
binary.LittleEndian.Uint64(bytesArrays[0:8])
这个"转换"的原因不起作用,是因为你的程序中没有转换。赋值不隐式地执行转换(接口类型除外)。
参见控制常量值赋值的可赋值规则:
如果满足下列条件之一,值x可赋值给类型为T的变量("x可赋值给T"):
- x的类型与t相同
- …
- x是一个无类型常量,可以用t类型的值表示。
在这种情况下,math.MinInt64
是一个无类型的常量,但它不能用uint64
类型的值表示,因为它是这样定义的:
uint64所有无符号64位整数(0 ~ 18446744073709551615)的集合
负64位整数和无符号64位整数之间的转换是可能的,但是你需要一个真正的转换。然而,由于一个熟悉的规则,您仍然不能直接转换常量值:
因此,正确的方法是首先将数字赋值给一个非常量值:如果x可以用T表示,则常数值x可以转换为类型T
x := int64(math.MinInt64)
y := uint64(x)
fmt.Println(y)
操场上联系
int64 fits确实适合uint64,但问题中的代码不是这样做的。这段代码为常数math赋值。MinInt64转换为uint64变量randomNum
。编译器报告一个错误,因为常量不能用uint64表示。
先赋值给一个变量,这样就不适用常量的规则了:
x := int64(math.MinInt64)
var randomNum = uint64(x)
fmt.Println(randomNum)
谁说你不行?编译器会这么说。但是编译器意味着你不能把值-9223372036854775808
放入uint64
变量中,这是真的;你需要把位模式,作为int64,表示-9223372036854775808,但表示值,它将被视为uint64到uint64
:
var randomNum uint64 = math.MinInt64 + math.MaxUint64 + 1
效果很好,当然也可以像GastroHealth展示的那样。
我主要研究这个,因为我想将[8]字节转换回具有适当符号的int64,但到目前为止,我只看到返回uint64的函数(例如
binary.LittleEndian.Uint64
)。
我们做显而易见的:
signed := int64(v ^ 0x8000000000000000 - 0x8000000000000000)
(好吧,一旦你看到它几次就很明显了。)
在这里查看完整的示例(我使用大端序,我更喜欢人类使用它)。注意,您可以在这里执行signed := int64(v)
;在没有变量的情况下,翻转减法技巧很适合用于表达式。