binary

原文:https://pkg.go.dev/encoding/binary@go1.23.0

Package binary implements simple translation between numbers and byte sequences and encoding and decoding of varints.

​ binary 包实现了数字与字节序列之间的简单转换以及可变整数的编码和解码。

Numbers are translated by reading and writing fixed-size values. A fixed-size value is either a fixed-size arithmetic type (bool, int8, uint8, int16, float32, complex64, …) or an array or struct containing only fixed-size values.

​ 通过读取和写入固定大小的值来转换数字。固定大小的值要么是固定大小的算术类型(bool、int8、uint8、int16、float32、complex64 等),要么是仅包含固定大小值的数组或结构。

The varint functions encode and decode single integer values using a variable-length encoding; smaller values require fewer bytes. For a specification, see https://developers.google.com/protocol-buffers/docs/encoding.

​ 可变整数函数使用可变长度编码对单个整数值进行编码和解码;较小的值需要更少的字节。有关规范,请参阅 https://developers.google.com/protocol-buffers/docs/encoding

This package favors simplicity over efficiency. Clients that require high-performance serialization, especially for large data structures, should look at more advanced solutions such as the encoding/gob package or protocol buffers.

​ 此软件包更注重简单性而不是效率。需要高性能序列化(尤其是对于大型数据结构)的客户端应该考虑更高级的解决方案,例如 encoding/gob 包或协议缓冲区。

常量

View Source

1
2
3
4
5
const (
	MaxVarintLen16 = 3
	MaxVarintLen32 = 5
	MaxVarintLen64 = 10
)

MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.

​ MaxVarintLenN 是经过可变整数编码的 N 位整数的最大长度。

变量

View Source

1
var BigEndian bigEndian

BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder.

​ BigEndian 是 ByteOrder 和 AppendByteOrder 的大端实现。

View Source

1
var LittleEndian littleEndian

LittleEndian is the little-endian implementation of ByteOrder and AppendByteOrder.

​ LittleEndian 是 ByteOrder 和 AppendByteOrder 的小端实现。

函数

func Append <- go1.23.0

1
func Append(buf []byte, order ByteOrder, data any) ([]byte, error)

Append appends the binary representation of data to buf. buf may be nil, in which case a new buffer will be allocated. See Write on which data are acceptable. It returns the (possibily extended) buffer containing data or an error.

​ Append 将数据的二进制表示追加到 buf。buf 可以为 nil,在这种情况下会分配一个新缓冲区。参见 Write,了解哪些数据是可接受的。它返回包含数据的(可能扩展的)缓冲区或一个错误。

func AppendUvarint <- go1.19

1
func AppendUvarint(buf []byte, x uint64) []byte

AppendUvarint appends the varint-encoded form of x, as generated by PutUvarint, to buf and returns the extended buffer.

​ AppendUvarint 将 x 的 varint 编码形式(由 PutUvarint 生成)追加到 buf 并返回扩展的缓冲区。

func AppendVarint <- go1.19

1
func AppendVarint(buf []byte, x int64) []byte

AppendVarint appends the varint-encoded form of x, as generated by PutVarint, to buf and returns the extended buffer.

​ AppendVarint 将 x 的 varint 编码形式(由 PutVarint 生成)追加到 buf 并返回扩展的缓冲区。

func Decode <- go1.23.0

1
func Decode(buf []byte, order ByteOrder, data any) (int, error)

Decode decodes binary data from buf into data according to the given byte order. It returns an error if buf is too small, otherwise the number of bytes consumed from buf.

​ Decode 根据给定的字节顺序,将 buf 中的二进制数据解码为 data。如果 buf 太小,它会返回一个错误,否则返回从 buf 中消耗的字节数。

func Encode <- go1.23.0

1
func Encode(buf []byte, order ByteOrder, data any) (int, error)

Encode encodes the binary representation of data into buf according to the given byte order. It returns an error if buf is too small, otherwise the number of bytes written into buf.

​ Encode 根据给定的字节顺序,将 data 的二进制表示编码到 buf 中。如果 buf 太小,它会返回一个错误,否则返回写入 buf 的字节数。

func PutUvarint

1
func PutUvarint(buf []byte, x uint64) int

PutUvarint encodes a uint64 into buf and returns the number of bytes written. If the buffer is too small, PutUvarint will panic.

​ PutUvarint 将 uint64 编码到 buf 中并返回写入的字节数。如果缓冲区太小,PutUvarint 将引发 panic。

PutUvarint Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	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])
	}
}

Output:

01
02
7f
8001
ff01
8002

func PutVarint

1
func PutVarint(buf []byte, x int64) int

PutVarint encodes an int64 into buf and returns the number of bytes written. If the buffer is too small, PutVarint will panic.

​ PutVarint 将 int64 编码到 buf 中并返回写入的字节数。如果缓冲区太小,PutVarint 将引发 panic。

PutVarint Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	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])
	}
}

Output:

8101
7f
03
01
00
02
04
7e
8001

func Read

1
func Read(r io.Reader, order ByteOrder, data any) error

Read reads structured binary data from r into data. Data must be a pointer to a fixed-size value or a slice of fixed-size values. Bytes read from r are decoded using the specified byte order and written to successive fields of the data. When decoding boolean values, a zero byte is decoded as false, and any other non-zero byte is decoded as true. When reading into structs, the field data for fields with blank (_) field names is skipped; i.e., blank field names may be used for padding. When reading into a struct, all non-blank fields must be exported or Read may panic.

​ Read 从 r 中读取结构化的二进制数据到 data 中。Data 必须是固定大小值的指针或固定大小值的切片。从 r 中读取的字节使用指定的字节顺序解码,并写入 data 的连续字段中。在解码布尔值时,零字节解码为 false,任何其他非零字节解码为 true。在读取结构时,具有空白 (_) 字段名的字段的数据将被跳过;即,空白字段名可用于填充。在读取结构时,所有非空白字段都必须导出,否则 Read 可能会引发 panic。

The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, Read returns ErrUnexpectedEOF.

​ 仅当未读取任何字节时,错误才是 EOF。如果在读取某些字节(但不是全部字节)后发生 EOF,Read 将返回 ErrUnexpectedEOF。

Read Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

func main() {
	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)
}

Output:

3.141592653589793

Read Example (Multi)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

func main() {
	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)
}

Output:

3.141592653589793
255
01 02 03
61374

func ReadUvarint

1
func ReadUvarint(r io.ByteReader) (uint64, error)

ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64. The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, ReadUvarint returns io.ErrUnexpectedEOF.

​ ReadUvarint 从 r 中读取编码的无符号整数,并将其作为 uint64 返回。仅当未读取任何字节时,错误才是 EOF。如果在读取某些字节(但不是全部字节)后发生 EOF,ReadUvarint 将返回 io.ErrUnexpectedEOF。

func ReadVarint

1
func ReadVarint(r io.ByteReader) (int64, error)

ReadVarint reads an encoded signed integer from r and returns it as an int64. The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, ReadVarint returns io.ErrUnexpectedEOF.

​ ReadVarint 从 r 读取一个编码的带符号整数并将其作为 int64 返回。仅当未读取任何字节时,错误才是 EOF。如果在读取某些字节(但不是全部字节)后发生 EOF,ReadVarint 将返回 io.ErrUnexpectedEOF。

func Size

1
func Size(v any) int

Size returns how many bytes Write would generate to encode the value v, which must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. If v is neither of these, Size returns -1.

​ Size 返回 Write 将生成多少字节来对值 v 进行编码,该值必须是固定大小的值或固定大小值的切片,或指向此类数据的指针。如果 v 不是其中任何一个,Size 将返回 -1。

func Uvarint

1
func Uvarint(buf []byte) (uint64, int)

Uvarint decodes a uint64 from buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 meaning:

​ Uvarint 从 buf 解码一个 uint64 并返回该值和读取的字节数(> 0)。如果发生错误,则值为 0,字节数 n <= 0,这意味着:

n == 0: buf too small
n  < 0: value larger than 64 bits (overflow)
        and -n is the number of bytes read

Uvarint Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	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)
	}
}

Output:

1
2
127
128
255
256

func Varint

1
func Varint(buf []byte) (int64, int)

Varint decodes an int64 from buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 with the following meaning:

​ Varint 从 buf 解码一个 int64 并返回该值和读取的字节数(> 0)。如果发生错误,则值为 0,字节数 n <= 0,含义如下:

n == 0: buf too small
n  < 0: value larger than 64 bits (overflow)
        and -n is the number of bytes read

Varint Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	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)
	}
}

Output:

-65
-64
-2
-1
0
1
2
63
64

func Write

1
func Write(w io.Writer, order ByteOrder, data any) error

Write writes the binary representation of data into w. Data must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. Boolean values encode as one byte: 1 for true, and 0 for false. Bytes written to w are encoded using the specified byte order and read from successive fields of the data. When writing structs, zero values are written for fields with blank (_) field names.

​ Write 将数据的二进制表示形式写入 w。Data 必须是固定大小的值或固定大小值的切片,或指向此类数据的指针。布尔值编码为一个字节:true 为 1,false 为 0。写入 w 的字节使用指定的字节顺序进行编码,并从数据的连续字段中读取。在编写结构时,对于具有空白 (_) 字段名的字段,将写入零值。

Write Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
)

func main() {
	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())
}

Output:

18 2d 44 54 fb 21 09 40

Write Example (Multi)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

func main() {
	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())
}

Output:

beefcafe

类型

type AppendByteOrder <- go1.19

1
2
3
4
5
6
type AppendByteOrder interface {
	AppendUint16([]byte, uint16) []byte
	AppendUint32([]byte, uint32) []byte
	AppendUint64([]byte, uint64) []byte
	String() string
}

AppendByteOrder specifies how to append 16-, 32-, or 64-bit unsigned integers into a byte slice.

​ AppendByteOrder 指定如何将 16 位、32 位或 64 位无符号整数追加到字节切片中。

type ByteOrder

1
2
3
4
5
6
7
8
9
type ByteOrder interface {
	Uint16([]byte) uint16
	Uint32([]byte) uint32
	Uint64([]byte) uint64
	PutUint16([]byte, uint16)
	PutUint32([]byte, uint32)
	PutUint64([]byte, uint64)
	String() string
}

A ByteOrder specifies how to convert byte slices into 16-, 32-, or 64-bit unsigned integers.

​ ByteOrder 指定如何将字节切片转换为 16 位、32 位或 64 位无符号整数。

ByteOrder Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	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)
}

Output:

0x03e8 0x07d0

ByteOrder Example (Put)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	b := make([]byte, 4)
	binary.LittleEndian.PutUint16(b[0:], 0x03e8)
	binary.LittleEndian.PutUint16(b[2:], 0x07d0)
	fmt.Printf("% x\n", b)
}

Output:

e8 03 d0 07
最后修改 October 10, 2024: 更新 (a4b8f85)