返回文章列表

文章

Go语言中的binary.LittleEndian的用法

在 Go 语言中,binary.LittleEndian.PutUint16(node[0:2], btype) 是一个用于处理二进制数据的操作,其用法和含义如下

目录
  1. 在 Go 语言中,binary.LittleEndian.PutUint16(node[0:2], btype) 是一个用于处理二进制数据的操作,其用法和含义如下:
  2. 代码结构解析
  3. 作用说明
  4. 示例
  5. 关键注意事项
  6. 常见用途

在 Go 语言中,binary.LittleEndian.PutUint16(node[0:2], btype) 是一个用于处理二进制数据的操作,其用法和含义如下:#

代码结构解析#

binary.LittleEndian.PutUint16(node[0:2], btype)
  1. binary** 包** 来自 Go 标准库的 encoding/binary 包,用于二进制数据的编码和解码。
  2. LittleEndian 表示使用 小端字节序(Little-Endian)对数据进行编码。
    • 小端字节序:低位字节在前(例如 0x1234 会存储为 0x34 0x12)。
    • 若需大端序,可使用 binary.BigEndian
  3. PutUint16** 方法** 将 16 位无符号整数(uint16)写入字节切片([]byte)。
    • 第一个参数:目标字节切片 node[0:2],必须至少有 2 字节容量(因为 uint16 占 2 字节)。
    • 第二个参数:要写入的整数值 btype(类型需为 uint16)。

作用说明#

  • 目的:将 btype 的值以小端格式写入 node 切片的 前 2 个字节
  • 典型场景
    • 网络协议数据包封装
    • 二进制文件格式写入
    • 内存中结构化数据的二进制表示

示例#

package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	var node = make([]byte, 2) // 创建一个 2 字节的切片
	var btype uint16 = 0x1234  // 要写入的值

	// 将 0x1234 以小端格式写入 node[0:2]
	binary.LittleEndian.PutUint16(node[0:2], btype)

	// 输出结果(小端序:低位在前)
	fmt.Printf("%x\n", node) // 输出: 3412
}

关键注意事项#

  1. 切片长度 目标切片必须至少有 2 字节容量,否则会触发 panic。例如:

node := make([]byte, 1) // 长度不足,运行时会报错 binary.LittleEndian.PutUint16(node, 0x1234) // panic: runtime error: slice bounds out of range 2. **类型匹配** 写入的值必须是 **`uint16`** 类型。若变量类型不匹配,需显式转换: go var btype int = 0x1234 binary.LittleEndian.PutUint16(node, uint16(btype)) // 强制转换 3. **字节序选择** 根据实际协议或格式要求选择字节序: go binary.BigEndian.PutUint16(node, btype) // 大端序(高位在前) <empty-block/> 4. 为什么输出是3412而不是1234 当使用 **`binary.LittleEndian.PutUint16`** 写入 **`0x1234`** 时:<br> 1. **数值分解** **`0x1234`** 是一个 16 位无符号整数(占 2 字节),可拆分为: - **高位字节**:**`0x12`**(对应二进制 **`00010010`**) - **低位字节**:**`0x34`**(对应二进制 **`00110100`**) 2. **小端序存储** - **低位字节在前**:**`0x34`** 存储在切片的前一个位置(索引 **`0`**) - **高位字节在后**:**`0x12`** 存储在切片的后一个位置(索引 **`1`**) 因此,写入后 **`node`** 切片的内容为: go node = []byte{0x34, 0x12} 3. **格式化输出** 使用 **`fmt.Printf("%x\n", node)`** 时: - **`%x`** 会将每个字节转换为两位十六进制字符串。 - 按切片顺序依次输出字节:**`0x34`** → **`34`**,**`0x12`** → **`12`**,合并为 **`3412`**。 ### **对比实验:大端序(Big-Endian)的输出** 如果将代码改为大端序: go binary.BigEndian.PutUint16(node[0:2], btype) ``` - 存储顺序:高位字节 0x12 在前(索引 0),低位字节 0x34 在后(索引 1)。 - 切片内容node = []byte{0x12, 0x34} - 输出结果1234 --- ### 内存布局可视化

**字节序****内存地址(低 → 高)****十六进制表示**
Little**`0x34`** **`0x12`****`3412`**
Big**`0x12`** **`0x34`****`1234`**
---
### **技术总结**
- **小端序**:低位字节存储在低地址,符合 x86/x64 架构的默认字节序。
- **大端序**:高位字节存储在低 地址,常见于网络协议(如 TCP/IP)和某些硬件架构。
- **实际应用**:
	字节序的选择需与数据接收方一致。例如,网络传输通常使用大端序(网络字节序),而本地存储可能使用小端序。
如果尝试写入其他值(如 **`0xAABB`**),小端序的输出将是 **`BBAA`**,而大端序为 **`AABB`**。这种差异在跨平台或协议通信时必须特别注意!
<empty-block/>

常见用途#

  • 序列化数据到字节流(如网络协议头、文件格式)
  • 与硬件寄存器或底层系统 API 交互
  • 优化内存布局(如手动控制结构体的二进制表示)