Есть ли лучший способ проверить порядок байтов в Go
Я пишу небольшую программу для проверки порядка байтов с помощью 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 {
// ...
}
я import "unsafe"
пакет для конвертации *int
в *byte
, Но, как упоминалось в https://golang.org/pkg/unsafe/:
Пакет unsafe содержит операции, которые обходят безопасность типов программ Go.
Пакеты, которые импортируются небезопасно, могут быть непереносимыми и не защищены рекомендациями по совместимости с Go 1.
Есть ли лучший способ определить порядковый номер, или я должен использовать небезопасный пакет?
3 ответа
Хотя все еще полагаясь на unsafe
В пакете Google TensorFlow API для Go есть отличное решение (см. tenors.go) для проверки порядка вашего компьютера:
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.")
}
}
То, что вы хотите сделать, зависит от архитектуры, и насколько я могу судить, Go не делает ничего, чтобы помочь вам определить порядок байтов вашего хоста. Ваше решение с использованием небезопасных указателей, вероятно, лучшее, что вы можете сделать.
Если вы знаете порядок байтов, в котором хотите говорить, и соответственно кодируете / декодируете, вы можете использовать encoding/binary
пакет для этого: https://godoc.org/encoding/binary
Если вам действительно нужно положиться на порядок байтов хоста, возможно, вы пытаетесь избежать анти-паттерна разработки, которого следует избегать, если это возможно: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
Также здесь идет оживленная дискуссия о голангах по этой самой теме с мнениями, высказанными по обе стороны дискуссии: https://groups.google.com/forum/
Эта ветка электронной почты имеет предложение Русса Кокса просто статически определить желаемый порядок байтов (или порядок байтов хоста), используя ограничения сборки:
Уже несколько месяцев наш код имеет:
var hbo = binary.LittleEndian // hack - нам нужен порядок байтов хоста!
поэтому мы можем использовать encoding.Binary для чтения.
Поместите это в файл с именем byteorder_amd64.go, и он перестанет быть хаком. Это не должно быть в стандартной библиотеке.
Надеюсь, это поможет...
var bigEndian = (*(*[2]uint8)(unsafe.Pointer(&[]uint16{1}[0])))[0] == 0
В стороне, я подозреваю, что ваша исходная логика незаконна:
var i int = 0x0100
ptr := unsafe.Pointer(&i)
if 0x01 == *(*byte)(ptr) {
Если вы бросите *T
к unsafe.Pointer
затем к другому типу, *U
, тогда U
а также T
должен иметь эквивалентный макет памяти. https://golang.org/pkg/unsafe/
Может быть, этот код поможет вам.
При этом можно проверить порядок байтов машины:
//true = big endian, false = little endian
func getEndian() (ret bool) {
var i int = 0x1
bs := (*[INT_SIZE]byte)(unsafe.Pointer(&i))
if bs[0] == 0 {
return true
} else {
return false
}
}