有没有更好的方法来检查 Go 中的字节顺序

问题描述 投票:0回答:5

我正在编写一个小程序来使用 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"
软件包将
*int
转换为
*byte
。 但正如https://golang.org/pkg/unsafe/中提到的:

包不安全包含绕过 Go 程序类型安全的操作。

导入不安全的包可能是不可移植的,并且不受 Go 1 兼容性指南的保护。

是否有更好的方法来确定字节顺序,或者我是否必须使用不安全的包?

go endianness
5个回答
19
投票

虽然仍然依赖于

unsafe
包,但 Google 的 TensorFlow API for Go 有一个很好的解决方案(参见 tensor.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.")
    }
}

5
投票

您想要做的是特定于体系结构的事情,据我所知,Go 并没有做太多事情来帮助您确定主机的字节顺序。使用不安全指针的解决方案可能是您能做的最好的解决方案。

如果您知道要使用的字节顺序并相应地进行编码/解码,则可以使用

encoding/binary
包:https://godoc.org/encoding/binary#ByteOrder

如果您确实需要依赖主机字节顺序,您可能会陷入一种设计反模式,您应该尽可能避免这种模式:https://commandcenter.blogspot.com/2012/04/byte- order-fallacy.html

这里还有关于 golang-nuts 的关于这个话题的热烈讨论,辩论双方都表达了自己的观点:https://groups.google.com/forum/#!topic/golang-nuts/3GEzwKfRRQw

该电子邮件线程有 Russ Cox 的建议,即使用构建约束静态定义所需的字节顺序(或主机字节顺序):

几个月来我们的代码已经:

var hbo = binary.LittleEndian // hack - 我们想要主机字节顺序!

所以我们可以使用encoding.Binary来读取东西。

将其放入名为 byteorder_amd64.go 的文件中并 它不再是一个黑客。它不需要在标准中 图书馆。

希望有帮助...


1
投票

也许这个代码可以帮助你。

这可以检查机器字节顺序:

//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
    }

}

1
投票
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/#Pointer


0
投票

从 Go 1.21.0 开始,stdlib 包

encoding/binary
最终导出
binary.NativeEndian
。如果您不关心其特定的字节顺序,而只想
binary.NativeEndian
进行正确的编码或解码,这应该足够了。

如果您的模块遵循“支持最后两个 Go(次要)版本”规则,那么您现在可以直接使用

binary.Native
,而无需滚动自己的支持功能或包。

最后,如果您想知道 concrete 原生字节顺序,不幸的是

binary.Native
没有明确告诉您,因为
String()
总是返回
"NativeEndian"
。因此,在这个特定的用例中,您必须进行如下测试:

little := binary.NativeEndian.Uint16([]byte{0x12, 0x34}) == uint16(0x3412)
© www.soinside.com 2019 - 2024. All rights reserved.