将 []byte 转为 Little/Big-Endian 有符号整数还是浮点数?
Posted
技术标签:
【中文标题】将 []byte 转为 Little/Big-Endian 有符号整数还是浮点数?【英文标题】:Go []byte to Little/Big-Endian Signed Integer or Float? 【发布时间】:2016-04-14 13:27:42 【问题描述】:我能够将[]byte
转换为无符号整数:
a := binary.LittleEndian.Uint16(sampleA)
b := binary.BigEndian.Uint32(sampleB)
这利用了 Go 包 https://golang.org/src/encoding/binary/binary.go 中的 BigEndian 和 LittleEndian 类型。
这提供了Uint16()
,但是没有等效的Int16()
或Float32()
。
有什么想法为什么不呢?还有,这应该怎么做?
【问题讨论】:
【参考方案1】:将数字类型转换为一系列字节([]byte
),反之亦然,这与endianness 有关。如何解释结果完全取决于您。
您只需要组装一个 16 位、32 位或 64 位的值,一旦完成,您就可以根据需要解释结果。
例如,如果您已经有一个uint16
值,要将其用作有符号值,您只需要一个类型conversion,因为uint16
和int16
的内存布局是相同的(转换从uint16
到int16
不会改变内存表示,只是类型):
a := binary.LittleEndian.Uint16(sampleA)
// If you need int16:
a2 := int16(a)
同样:
a := binary.LittleEndian.Uint64(sampleA)
// If you need int64:
a2 := int64(a)
使用 uint -> float 转换的情况稍微复杂一些,因为使用简单的类型转换会尝试转换数值,而不仅仅是更改类型(因此会更改内存表示)。
对于将无符号整数转换为浮点类型,您可以使用math
包的函数,即math.Float32frombits()
和math.Float64frombits()
,并且对于具有相同内存的相反方向(将浮点值转换为无符号整数)布局:math.Float32bits()
和 math.Float64bits()
。
例如:
a := binary.LittleEndian.Uint64(sampleA)
// If you need a float64:
a2 := math.Float64frombits(a)
如果您从 math
包中查看这些函数的实现,您会发现内存值/布局没有被操纵,它只是被“查看”为不同的类型,通过使用 unsafe
包裹。例如:
func Float32frombits(b uint32) float32 return *(*float32)(unsafe.Pointer(&b))
正如 Paul 所提到的,binary
包提供了 Read()
和 Write()
函数来在后台进行这些转换,因此您不需要这样做。
使用相同的“pi”示例进行展示(来自binary.Read()
的文档):
b := []byte0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40
// USING binary.Read()
var pi float64
buf := bytes.NewReader(b)
err := binary.Read(buf, binary.LittleEndian, &pi)
if err != nil
fmt.Println("binary.Read failed:", err)
fmt.Println(pi)
// Using LittleEndian.Uint64() and math.Float64frombits()
a := binary.LittleEndian.Uint64(b)
a2 := math.Float64frombits(a)
fmt.Println(a2)
输出(在Go Playground 上试试):
3.141592653589793
3.141592653589793
【讨论】:
【参考方案2】:ByteOrder
类型提供用于解码二进制值的低级 API。要读取 float64 或其他类型,可以使用binary.Read
。 godoc page for the binary package 上有一个example,我在这里复制了它:
var pi float64
b := []byte0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40
buf := bytes.NewReader(b)
err := binary.Read(buf, binary.LittleEndian, &pi)
if err != nil
fmt.Println("binary.Read failed:", err)
fmt.Print(pi)
没有用于解码 float16 的函数,因为这不是 Go 中的类型。
【讨论】:
以上是关于将 []byte 转为 Little/Big-Endian 有符号整数还是浮点数?的主要内容,如果未能解决你的问题,请参考以下文章
java 如何将string src = "ff" 转为 byte[] bt = (byte)0xff
将 []byte 转为 Little/Big-Endian 有符号整数还是浮点数?