在golang的binary包中有2个字节系的变量定义BigEndian和LittleEndian 这个东西是go里面很有特点的玩意,我们在java, php等语言中是基本看不到,因为大部分的语言默认使用的是BigEndian 大端模式, 而go语言里面是你自己可选的。
这个字节系大小端是与编译器运行平台的CPU架构有关, x86架构的CPU使用的是小端LittleEndian, 而x64架构的CPU基本上使用的是大端 。如果你是在C/C++里面以x86编译的程序和JAVA进行通信的话,这个大小端的差别就会让你大吃一惊!
这东西看似神秘,其实要理解它也很简单, 假设你将数字 1 存入内存, 在大端BigEndian模式时写入内存的是 01, 而小端LittleEndian模式时写入内存的是 10
用官方的解释来说就是
binary.BigEndian(大端模式):内存的低地址存放着数据高位
binary.LittleEndian(小端模式): 内存的低地址存放着数据低位
示例代码 大小端单元测试用例
package test
import (
"bytes"
"encoding/binary"
"fmt"
)
type Demo struct {
N16 uint16
N32 uint32
}
func ExampleBianry() {
// 对象
ss := &Demo{N16: 1, N32: 2}
var bufferB, bufferL bytes.Buffer
// 这里的binary的写入模式有2种:BigEndian 大端 , LittleEndian 小端; 假设都是写入1到内存,大端就是 01 而小端是 10
binary.Write(&bufferB, binary.BigEndian, ss)
// buffer大端结果: []uint8 len: 6, cap: 64, [0,1,0,0,0,2]
binary.Write(&bufferL, binary.LittleEndian, ss)
// buffer小端结果: []uint8 len: 6, cap: 64, [1,0,2,0,0,0]
fmt.Println("\n大端bufferB: ", bufferB.Bytes())
fmt.Println("小端bufferL: ", bufferL.Bytes())
var n uint64 = 2
var buffer_b bytes.Buffer
var buffer_l bytes.Buffer
binary.Write(&buffer_b, binary.BigEndian, n) // []uint8 len: 8, cap: 64, [0,0,0,0,0,0,0,2]
binary.Write(&buffer_l, binary.LittleEndian, n) // []uint8 len: 8, cap: 64, [2,0,0,0,0,0,0,0]
fmt.Printf("n=%d大端: %v \n", n, buffer_b.Bytes())
fmt.Printf("n=%d小端: %v \n", n, buffer_l.Bytes())
// output:
// 大端bufferB: [0 1 0 0 0 2]
// 小端bufferL: [1 0 2 0 0 0]
// n=2大端: [0 0 0 0 0 0 0 2]
// n=2小端: [2 0 0 0 0 0 0 0]
}
Debug运行示意图
binary.write数据写入注意事项:
1. Write将数据的二进制表示形式写入buf。
2. 数据必须是固定大小的值或固定大小值的切片,或指向此类数据的指针。
这里的固定大小必须是有明确的位数的,如int8, int16, float64 等, 注意 int 类型的数据不能用于Write写入。
3. 布尔值编码为一个字节:1表示真,0表示假。