Что такое порядок байтов Big-Endian и Little-Endian и как с ним работать в Go?

Ответ

Big-endian и little-endian — это два способа упорядочивания байтов при хранении многобайтовых типов данных (например, int32, float64) в памяти компьютера.

Представим число 0x12345678 (305 419 896 в десятичной системе), которое занимает 4 байта: 12, 34, 56, 78.

  • Big-endian (прямой порядок байтов): Старший (наиболее значащий) байт хранится по младшему адресу памяти. Это похоже на то, как мы читаем и пишем числа слева направо.

    • Память: [12] [34] [56] [78]
    • Пример: Сетевые протоколы (TCP/IP), процессоры PowerPC, ARM (может быть и тем, и другим).
  • Little-endian (обратный порядок байтов): Младший (наименее значащий) байт хранится по младшему адресу памяти.

    • Память: [78] [56] [34] [12]
    • Пример: Процессоры x86, x86-64 (Intel, AMD).

Работа в Go

В Go для работы с порядком байтов используется пакет encoding/binary. Это критически важно при работе с сетевыми протоколами или бинарными файлами, чтобы обеспечить корректное чтение и запись данных на разных платформах.

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    // Наше 4-байтное число
    num := uint32(0x12345678)

    // Буфер для хранения байтов
    buf := make([]byte, 4)

    // Записываем число в буфер в формате Big-Endian (сетевой порядок)
    binary.BigEndian.PutUint32(buf, num)
    fmt.Printf("Big-endian:    % xn", buf) // Вывод: 12 34 56 78

    // Записываем число в буфер в формате Little-Endian (порядок x86)
    binary.LittleEndian.PutUint32(buf, num)
    fmt.Printf("Little-endian: % xn", buf) // Вывод: 78 56 34 12

    // Чтение из Little-Endian буфера
    readNum := binary.LittleEndian.Uint32(buf)
    fmt.Printf("Прочитанное число: 0x%xn", readNum) // Вывод: 0x12345678
}