Converting int32 to uint64 and back to int32
time.Unix() int64 to int32 wrong conversion of after "2038-01-19"
How to convert an int64 to int in Go? - Stack Overflow
Using int32 for efficiency or simply stick to int64?
I am a bit concerned about a piece of code I wrote. It seems to work but I did not quite expect it to...
How does type conversion exactly work in Go when I convert a int32 to uint64 and then back to int32. I was somewhat scared that funny business might happen.
To give practical context of what I am doing. I have data like:
type data struct {
a uint16
b uint8
c uint8
d int32
}
Instead of using a data struct I want to package all the values in a single uint64 like:
data := uint64(a) | uint64(b)<<16 | uint64(c)<<24 | uint64(d)<<32
and then unpack it like (shifting back and applying a bit mask if necessary):
d := int32(data>>32)
my worries were around:
data = uint64(int32(d))
I was worried that it would try to do some conversion from int32 with negative values. But running some tests all it seems to be doing is padding or truncating bits and interpreting the two's compliment int values as uint.
Is this all safe and correct or am I about to run into nightmarish bugs?
Edit: In essence what I am asking with go type conversions does this hold for every value of d of type int32 :
d == int32(uint64(d))
You convert them with a type "conversion"
var a int
var b int64
int64(a) < b
When comparing values, you always want to convert the smaller type to the larger. Converting the other way will possibly truncate the value:
var x int32 = 0
var y int64 = math.MaxInt32 + 1 // y == 2147483648
if x < int32(y) {
// this evaluates to false, because int32(y) is -2147483648
Or in your case to convert the maxInt int64 value to an int, you could use
for a := 2; a < int(maxInt); a++ {
which would fail to execute correctly if maxInt overflows the max value of the int type on your system.
I came here because of the title, "How to convert an int64 to int in Go?". The answer is,
int(int64Var)
I have a field in my data which is small enough to simply use an int32. However, from what I can tell, int32 is generally used when representing a code point or something quite specific, rather than using it simply to save 32 bits of storage. Also, some of the stdlib packages (like strconv) deal exclusively with int64 rather than int32. This has meant changes to my code I didn't expect purely to handle int32 things.
What is your opinion (and perhaps the general consensus) on using int32 purely for efficiency purposes? Is it just worth using an int64 for simplicity?
func ParseInt(s string, base int, bitSize int) (i int64, err error)
ParseInt always returns int64.
bitSize defines the range of values.
If the value corresponding to s cannot be represented by a signed integer of the given size, err.Err = ErrRange.
http://golang.org/pkg/strconv/#ParseInt
type int int
int is a signed integer type that is at least 32 bits in size. It is a distinct type, however, and not an alias for, say, int32.
http://golang.org/pkg/builtin/#int
So int could be bigger than 32 bit in the future or on some systems like int in C.
I guess on some systems int64 might be faster than int32 because that system only works with 64-bit integers.
Here is an example of an error when bitSize is 8:
http://play.golang.org/p/_osjMqL6Nj
package main
import (
"fmt"
"strconv"
)
func main() {
i, err := strconv.ParseInt("123456", 10, 8)
fmt.Println(i, err)
}
Package strconv
func ParseInt
func ParseInt(s string, base int, bitSize int) (i int64, err error)ParseInt interprets a string s in the given base (2 to 36) and returns the corresponding value i. If base == 0, the base is implied by the string's prefix: base 16 for "0x", base 8 for "0", and base 10 otherwise.
The bitSize argument specifies the integer type that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 correspond to int, int8, int16, int32, and int64.
The errors that ParseInt returns have concrete type *NumError and include err.Num = s. If s is empty or contains invalid digits, err.Err = ErrSyntax; if the value corresponding to s cannot be represented by a signed integer of the given size, err.Err = ErrRange.
ParseInt always returns an int64 value. Depending on bitSize, this value will fit into int, int8, int16, int32, or int64. If the value cannot be represented by a signed integer of the size given by bitSize, then err.Err = ErrRange.
The Go Programming Language Specification
Numeric types
The value of an n-bit integer is n bits wide and represented using two's complement arithmetic.
int8 the set of all signed 8-bit integers (-128 to 127) int16 the set of all signed 16-bit integers (-32768 to 32767) int32 the set of all signed 32-bit integers (-2147483648 to 2147483647) int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)There is also a set of predeclared numeric types with implementation-specific sizes:
uint either 32 or 64 bits int same size as uint
int is either 32 or 64 bits, depending on the implementation. Usually it's 32 bits for 32-bit compilers and 64 bits for 64-bit compilers.
To find out the size of an int or uint, use strconv.IntSize.
Package strconv
Constants
const IntSize = intSize
IntSizeis the size in bits of anintoruintvalue.
For example,
package main
import (
"fmt"
"runtime"
"strconv"
)
func main() {
fmt.Println(runtime.Compiler, runtime.GOARCH, runtime.GOOS)
fmt.Println(strconv.IntSize)
}
Output:
gc amd64 linux
64
how can I do this.
I tried with this function, but it didn't work. :c
func changeType(arr []int32) []int64{
var arr2 []int64
for i := 0; i < len(arr); i++{
arr2[i] = int64(arr[i])
}
return arr2
}
I have the following function, it works flawlessly
func (r *system) Quantity() int32 {
// r.info.Quantity is type int
return int32(r.info.Quantity)
}Now I'm trying to cast it to *int32
func (r *system) Quantity() *int32 {
// r.info.Quantity is type int
return int32(&r.info.Quantity)
}
But i get the following error cannot use &r.info.Quantity (type *int) as type *int32 in return argument, and of course it seems logic...is there a way to achieve this?