Есть ли лучший способ проверить порядок байтов в 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
    }

}
Другие вопросы по тегам