I am writing a small program to check the endianness using Go:
var i int = 0x0100
ptr := unsafe.Pointer(&i)
if 0x01 == *(*byte)(ptr) {
fmt.Println("Big Endian")
} else if 0x00 == *(*byte)(ptr) {
fmt.Println("Little Endian")
} else {
// ...
}
I import "unsafe"
package to convert *int
to *byte
.
But as mentioned in https://golang.org/pkg/unsafe/:
Package unsafe contains operations that step around the type safety of Go programs.
Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
Is there a better way to determine endianness, or do I have to use unsafe package?
Is there a quick way to determine endianness of your machine? There are n no. of ways for determining endianness of your machine.
If it is little-endian, it would be stored as “01 00 00 00”. The program checks the first byte by dereferencing the cptr pointer. If it equals to 0, it means the processor is big-endian(“00 00 00 01”), If it equals to 1, it means the processor is little-endian (“01 00 00 00”).
Big-endian is an order in which the "big end" (most significant value in the sequence) is stored first, at the lowest storage address. Little-endian is an order in which the "little end" (least significant value in the sequence) is stored first.
By far the most common ordering of multiple bytes in one number is the little-endian, which is used on all Intel processors.
Although still relying on the unsafe
package, Google's TensorFlow API for Go has a nice solution (see tensor.go) for testing the endianness of your machine:
var nativeEndian binary.ByteOrder
func init() {
buf := [2]byte{}
*(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD)
switch buf {
case [2]byte{0xCD, 0xAB}:
nativeEndian = binary.LittleEndian
case [2]byte{0xAB, 0xCD}:
nativeEndian = binary.BigEndian
default:
panic("Could not determine native endianness.")
}
}
What you want to do is architecture-specific, and Go doesn't do a whole lot to help you determine your host's byte order as far as I can tell. Your solution using unsafe pointers is probably the best you can do.
If you know the byte order you want to speak in and encode/decode accordingly, you can use the encoding/binary
package for that: https://godoc.org/encoding/binary#ByteOrder
If you truly need to rely on host byte order, you might be banging your head on a design anti-pattern that you should try to avoid if possible: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
Also here's a spirited discussion on golang-nuts about this very topic, with opinions expressed on both sides of the debate: https://groups.google.com/forum/#!topic/golang-nuts/3GEzwKfRRQw
That email thread has a suggestion by Russ Cox to just statically define the desired byte order (or the host byte order) using build constraints:
For months now our code has had:
var hbo = binary.LittleEndian // hack - we want host byte order!
so we can use encoding.Binary to read things.
Put that in a file named byteorder_amd64.go and it stops being a hack. It need not be in the standard library.
Hope that helps...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With