What you are asking (to store 18,446,744,073,709,551,615 as an int64
value) is impossible.
A unit64
stores positive integers and has 64 bits available to hold information. It can therefore store any positive integer between 0 and 18,446,744,073,709,551,615 (2^64-1).
An int64
uses one bit to hold the sign, leaving 63 bits to hold information about the number. It can store any value between -9,223,372,036,854,775,808 and +9,223,372,036,854,775,807 (-2^63 and 2^63-1).
Both types can hold 18,446,744,073,709,551,616 unique integers, it is just that the uint64
range starts at zero, where as the int64
values straddle zero.
To hold 18,446,744,073,709,551,615 as a signed integer would require 65 bits.
In your conversion, no information from the underlying bytes is lost. The difference in the integer values returned is due to how the the two types interpret and display the values.
uint64
will display a raw integer value, whereas int64
will use two's complement.
var x uint64 = 18446744073709551615
var y int64 = int64(x)
fmt.Printf("uint64: %v = %#[1]x, int64: %v = %#x
", x, y, uint64(y))
// uint64: 18446744073709551615 = 0xffffffffffffffff
// int64: -1 = 0xffffffffffffffff
x -= 100
y -= 100
fmt.Printf("uint64: %v = %#[1]x, int64: %v = %#x
", x, y, uint64(y))
// uint64: 18446744073709551515 = 0xffffffffffffff9b
// int64: -101 = 0xffffffffffffff9b
https://play.golang.com/p/hlWqhnC9Dh