...

パッケージ binary

import "encoding/binary"
概要
目次

概要 ▾

binary パッケージは数,バイトシーケンスと varint のエンコード,デコードのシンプルな変換を提供します。

数値は固定サイズの値を読み書きすることによって変換されます。 固定サイズ値は,固定サイズ算術型 (bool, int8, uint8, int16, float32, complex64 など),または固定サイズの値のみを含む配列または構造体です。

varint 関数は,可変長エンコードを使用して 1 つの整数値をエンコードおよびデコードします。 値が小さいほど必要なバイト数が少なくなります。 仕様については, https://developers.google.com/protocol-buffers/docs/encoding を参照してください。

このパッケージは効率より単純さを優先します。 特に大規模なデータ構造で高性能のシリアル化を必要とするクライアントは, encoding/gob パッケージやプロトコルバッファなどのより高度なソリューションを検討する必要があります。

定数

MaxVarintLenN は, varint エンコードされた N ビット整数の最大長です。

const (
    MaxVarintLen16 = 3
    MaxVarintLen32 = 5
    MaxVarintLen64 = 10
)

変数

BigEndian は, ByteOrder のビッグエンディアン実装です。

var BigEndian bigEndian

LittleEndian は, ByteOrder のリトルエンディアン実装です。

var LittleEndian littleEndian

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 interface{}) error

Read は,構造化バイナリデータを r から data に読み込みます。 data は,固定サイズ値へのポインタまたは固定サイズ値のスライスでなければなりません。 r から読み取られたバイトは,バイトオーダー order を使用してデコードされ,data の連続したフィールドに書き込まれます。 ブール値をデコードするとき,ゼロバイトは false としてデコードされ,ゼロ以外のバイトはすべて true としてデコードされます。 構造体を読み込むとき,空白 (_) のフィールド名を持つフィールドのフィールドデータはスキップされます。 つまり,空白のフィールド名をパディングに使用することができます。 構造体を読み込むときは,空白以外のすべてのフィールドをエクスポートする必要があります。 そうしないと,Read はパニックします。

バイトが読み取られなかった場合のみ,エラーは EOF です。 すべてのバイトではなく一部のバイトを読み取った後に EOF が発生した場合, Read は 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

例 (Multi)

コード:

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 として返します。

func ReadVarint

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

ReadVarint は, r からエンコードされた符号付き整数を読み取り,それを int64 として返します。

func Size

func Size(v interface{}) int

Size は,値 v をエンコードするために Write が生成するバイト数を返します。 値 v は,固定サイズ値または固定サイズ値のスライス,またはそのようなデータへのポインタである必要があります。 v がどちらでもない場合, Size は -1 を返します。

func Uvarint

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

Uvarint は, buf から uint64 をデコードし,その値と読み込んだバイト数 (> 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 は buf から int64 をデコードし,その値と読み込んだバイト数 (> 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 interface{}) error

Write は data のバイナリ表現を w に書き込みます。 data は,固定サイズ値または固定サイズ値のスライス,あるいはそのようなデータへのポインタでなければなりません。 ブール値は 1 バイトとしてエンコードされます。 true の場合は 1 , false の場合は 0 です。 w に書き込まれたバイトは,バイトオーダー order を使用してエンコードされ,データの連続したフィールドから読み取られます。 構造体を書き込む,空白 (_) フィールド名を持つフィールドではゼロ値が書き込まれます。

コード:

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

例 (Multi)

コード:

buf := new(bytes.Buffer)
var data = []interface{}{
    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 ByteOrder

ByteOrder は,バイトシーケンスを 16, 32, または 64 ビットの符号なし整数に変換する方法を指定します。

type ByteOrder interface {
    Uint16([]byte) uint16
    Uint32([]byte) uint32
    Uint64([]byte) uint64
    PutUint16([]byte, uint16)
    PutUint32([]byte, uint32)
    PutUint64([]byte, uint64)
    String() string
}

例 (Get)

コード:

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

例 (Put)

コード:

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