Пакет binary
Обзор
Пакет binary реализует простое преобразование чисел в последовательности байтов и обратно, а также кодирование и декодирование varint.
Преобразование чисел выполняется чтением и записью значений фиксированного размера. Значение фиксированного размера — это либо арифметический тип фиксированного размера (bool, int8, uint8, int16, float32, complex64, ...), либо массив или структура, содержащие только значения фиксированного размера.
Функции varint кодируют и декодируют отдельные целочисленные значения с помощью кодирования переменной длины; для меньших значений требуется меньше байтов. Спецификацию см. на странице https://developers.google.com/protocol-buffers/docs/encoding.
Этот пакет отдает предпочтение простоте, а не эффективности. Клиентам, которым требуется высокопроизводительная сериализация, особенно для больших структур данных, следует рассмотреть более продвинутые решения, такие как пакет encoding/gob или google.golang.org/protobuf для protocol buffers.
Указатель
Примеры
Файлы пакета
binary.go native_endian_little.go varint.go
Константы
MaxVarintLenN — максимальная длина целого числа из N бит, закодированного в формате varint.
const (
MaxVarintLen16 = 3
MaxVarintLen32 = 5
MaxVarintLen64 = 10
) Переменные
BigEndian — реализация с порядком байтов от старшего к младшему для ByteOrder и AppendByteOrder.
var BigEndian bigEndian
LittleEndian — реализация с порядком байтов от младшего к старшему для ByteOrder и AppendByteOrder.
var LittleEndian littleEndian
NativeEndian — реализация с собственным порядком байтов платформы для ByteOrder и AppendByteOrder.
var NativeEndian nativeEndian
func Append 1.23
func Append(buf []byte, order ByteOrder, data any) ([]byte, error)
Append добавляет двоичное представление data в buf. buf может быть nil; в этом случае будет выделен новый буфер. Допустимые значения data см. в описании Write. Функция возвращает буфер, содержащий data (возможно, расширенный), или ошибку.
func AppendUvarint 1.19
func AppendUvarint(buf []byte, x uint64) []byte
AppendUvarint добавляет в buf форму x, закодированную в формате varint, как при вызове PutUvarint, и возвращает расширенный буфер.
func AppendVarint 1.19
func AppendVarint(buf []byte, x int64) []byte
AppendVarint добавляет в buf форму x, закодированную в формате varint, как при вызове PutVarint, и возвращает расширенный буфер.
func Decode 1.23
func Decode(buf []byte, order ByteOrder, data any) (int, error)
Decode декодирует двоичные данные из buf в data в соответствии с заданным порядком байтов. Если buf слишком мал, функция возвращает ошибку; в противном случае она возвращает количество байтов, считанных из buf.
func Encode 1.23
func Encode(buf []byte, order ByteOrder, data any) (int, error)
Encode кодирует двоичное представление data в buf в соответствии с заданным порядком байтов. Если buf слишком мал, функция возвращает ошибку; в противном случае она возвращает количество байтов, записанных в buf.
func PutUvarint
func PutUvarint(buf []byte, x uint64) int
PutUvarint кодирует uint64 в buf и возвращает количество записанных байтов. Если буфер слишком мал, PutUvarint вызовет панику.
Пример
Код:
buf := make([]byte, binary.MaxVarintLen64)
for _, x := range []uint64{1, 2, 127, 128, 255, 256} {
n := binary.PutUvarint(buf, x)
fmt.Printf("%x\n", buf[:n])
}
Вывод:
01 02 7f 8001 ff01 8002
func PutVarint
func PutVarint(buf []byte, x int64) int
PutVarint кодирует int64 в buf и возвращает количество записанных байтов. Если буфер слишком мал, PutVarint вызовет панику.
Пример
Код:
buf := make([]byte, binary.MaxVarintLen64)
for _, x := range []int64{-65, -64, -2, -1, 0, 1, 2, 63, 64} {
n := binary.PutVarint(buf, x)
fmt.Printf("%x\n", buf[:n])
}
Вывод:
8101 7f 03 01 00 02 04 7e 8001
func Read
func Read(r io.Reader, order ByteOrder, data any) error
Read считывает структурированные двоичные данные из r в data. Data должен быть указателем на значение фиксированного размера или срез значений фиксированного размера. Байты, считанные из r, декодируются с использованием заданного порядка байтов и записываются в последовательные поля data. При декодировании логических значений нулевой байт преобразуется в false, а любой ненулевой байт — в true. При чтении в структуры данные полей с пустыми (_) именами пропускаются; то есть пустые имена полей можно использовать для заполнения. При чтении в структуру все непустые поля должны быть экспортируемыми, иначе Read может вызвать панику.
Ошибка имеет значение io.EOF только в том случае, если не было прочитано ни одного байта. Если io.EOF возникает после чтения части, но не всех байтов, Read возвращает io.ErrUnexpectedEOF.
Пример
Код:
var pi float64
b := []byte{0x18, 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)
Вывод:
3.141592653589793
Пример (несколько значений)
Код:
b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40, 0xff, 0x01, 0x02, 0x03, 0xbe, 0xef}
r := bytes.NewReader(b)
var data struct {
PI float64
Uate uint8
Mine [3]byte
Too uint16
}
if err := binary.Read(r, binary.LittleEndian, &data); err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Println(data.PI)
fmt.Println(data.Uate)
fmt.Printf("% x\n", data.Mine)
fmt.Println(data.Too)
Вывод:
3.141592653589793 255 01 02 03 61374
func ReadUvarint
func ReadUvarint(r io.ByteReader) (uint64, error)
ReadUvarint считывает из r закодированное беззнаковое целое число и возвращает его в виде uint64. Ошибка io.EOF возникает только в том случае, если не было прочитано ни одного байта. Если io.EOF возникает после чтения некоторых, но не всех байтов, ReadUvarint возвращает io.ErrUnexpectedEOF.
func ReadVarint
func ReadVarint(r io.ByteReader) (int64, error)
ReadVarint считывает из r закодированное знаковое целое число и возвращает его в виде int64. Ошибка io.EOF возникает только в том случае, если не было прочитано ни одного байта. Если io.EOF возникает после чтения некоторых, но не всех байтов, ReadVarint возвращает io.ErrUnexpectedEOF.
func Size
func Size(v any) int
Size возвращает количество байтов, которое Write запишет для кодирования значения v. Значение должно иметь фиксированный размер, быть срезом значений фиксированного размера или указателем на такие данные. Если v не относится ни к одному из этих типов, Size возвращает -1.
func Uvarint
func Uvarint(buf []byte) (uint64, int)
Uvarint декодирует uint64 из buf и возвращает это значение и количество прочитанных байтов (> 0). При возникновении ошибки значение равно 0, а количество байтов n <= 0, что означает:
- n == 0: буфер buf слишком мал;
- n < 0: значение превышает 64 бита (переполнение), а -n — количество прочитанных байтов.
Пример
Код:
inputs := [][]byte{
{0x01},
{0x02},
{0x7f},
{0x80, 0x01},
{0xff, 0x01},
{0x80, 0x02},
}
for _, b := range inputs {
x, n := binary.Uvarint(b)
if n != len(b) {
fmt.Println("Uvarint did not consume all of in")
}
fmt.Println(x)
}
Вывод:
1 2 127 128 255 256
func Varint
func Varint(buf []byte) (int64, int)
Varint декодирует int64 из buf и возвращает это значение и количество прочитанных байтов (> 0). При возникновении ошибки значение равно 0, а количество байтов n <= 0, что означает:
- n == 0: буфер buf слишком мал;
- n < 0: значение превышает 64 бита (переполнение), а -n — количество прочитанных байтов.
Пример
Код:
inputs := [][]byte{
{0x81, 0x01},
{0x7f},
{0x03},
{0x01},
{0x00},
{0x02},
{0x04},
{0x7e},
{0x80, 0x01},
}
for _, b := range inputs {
x, n := binary.Varint(b)
if n != len(b) {
fmt.Println("Varint did not consume all of in")
}
fmt.Println(x)
}
Вывод:
-65 -64 -2 -1 0 1 2 63 64
func Write
func Write(w io.Writer, order ByteOrder, data any) error
Write записывает двоичное представление данных в w. Данные должны иметь фиксированный размер, быть срезом данных фиксированного размера или указателем на такие данные. Логические значения кодируются одним байтом: 1 для true и 0 для false. Байты записываются в w в указанном порядке байтов и считываются из последовательных полей данных. При записи структур для полей с пустыми именами (_) записываются нулевые значения.
Пример
Код:
buf := new(bytes.Buffer)
var pi float64 = math.Pi
err := binary.Write(buf, binary.LittleEndian, pi)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
fmt.Printf("% x", buf.Bytes())
Вывод:
18 2d 44 54 fb 21 09 40
Пример (несколько значений)
Код:
buf := new(bytes.Buffer)
var data = []any{
uint16(61374),
int8(-54),
uint8(254),
}
for _, v := range data {
err := binary.Write(buf, binary.LittleEndian, v)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
}
fmt.Printf("%x", buf.Bytes())
Вывод:
beefcafe
type AppendByteOrder 1.19
AppendByteOrder определяет, как добавлять беззнаковые целые числа размером 16, 32 или 64 бита в срез байтов.
Этот интерфейс реализуют LittleEndian, BigEndian и NativeEndian.
type AppendByteOrder interface {
AppendUint16([]byte, uint16) []byte
AppendUint32([]byte, uint32) []byte
AppendUint64([]byte, uint64) []byte
String() string
} type ByteOrder
ByteOrder определяет, как преобразовывать срезы байтов в беззнаковые целые числа размером 16, 32 или 64 бита.
Этот интерфейс реализуют LittleEndian, BigEndian и NativeEndian.
type ByteOrder interface {
Uint16([]byte) uint16
Uint32([]byte) uint32
Uint64([]byte) uint64
PutUint16([]byte, uint16)
PutUint32([]byte, uint32)
PutUint64([]byte, uint64)
String() string
} Пример (получение)
Код:
b := []byte{0xe8, 0x03, 0xd0, 0x07}
x1 := binary.LittleEndian.Uint16(b[0:])
x2 := binary.LittleEndian.Uint16(b[2:])
fmt.Printf("%#04x %#04x\n", x1, x2)
Вывод:
0x03e8 0x07d0
Пример (запись)
Код:
b := make([]byte, 4)
binary.LittleEndian.PutUint16(b[0:], 0x03e8)
binary.LittleEndian.PutUint16(b[2:], 0x07d0)
fmt.Printf("% x\n", b)
Вывод:
e8 03 d0 07
© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/encoding/binary/