関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。たまにやりたいときに忘れるのでここにメモメモ。
たまーになのですが、構造体の中身をそのままバイナリに出力したいときがあります。(通信で流したいときとか、Cとかから読みたいとか)
注意点は、stringやスライス、マップ、チャネルなどは、そのままでは binary.Writeに通らないという点ですね。つまり、fixed-size である必要があります。なので、文字列などはバイト配列にする必要があります。
サンプル
package main import ( "bytes" "encoding/binary" "encoding/hex" "fmt" "math" "os" "unsafe" ) type St1 struct { V1 int32 V2 uint32 V3 [8]byte V4 uint64 V5 [8]byte } func main() { s := St1{} fmt.Printf("sizeof=%d, alignof=%d\n", unsafe.Sizeof(s), unsafe.Alignof(s)) s.V1 = math.MaxInt32 s.V2 = math.MaxUint32 copy(s.V3[:], []byte{0xde, 0xad, 0xbe, 0xef}) s.V4 = math.MaxUint64 copy(s.V5[:], []byte("hello")) // // Write // file, err := os.Create("v1.bin") if err != nil { panic(err) } defer file.Close() err = binary.Write(file, binary.BigEndian, &s) if err != nil { panic(err) } err = file.Sync() if err != nil { panic(err) } // // Read // file2, err := os.Open("v1.bin") if err != nil { panic(err) } defer file2.Close() var s2 St1 err = binary.Read(file2, binary.BigEndian, &s2) if err != nil { panic(err) } // // Dump // var b1, b2 bytes.Buffer binary.Write(&b1, binary.BigEndian, s) binary.Write(&b2, binary.BigEndian, s2) fmt.Println(hex.Dump(b1.Bytes())) fmt.Println(hex.Dump(b2.Bytes())) }
binary.Write() に、&s
とポインタを渡していますが、これは実体でもポインタでも大丈夫です。
binary.Write() の中で
reflect.Indirect(reflect.ValueOf(data))
とやっていますので、どちらにせよ指し示す値で処理されます。
逆に、binary.Read()の場合は渡した構造体の中身を変更してもらわないといけないので、ポインタで指定しなければなりません。
$ task run task: [build] go mod tidy task: [build] go build -o app main.go task: [run] ./app sizeof=32, alignof=8 00000000 7f ff ff ff ff ff ff ff de ad be ef 00 00 00 00 |................| 00000010 ff ff ff ff ff ff ff ff 68 65 6c 6c 6f 00 00 00 |........hello...| 00000000 7f ff ff ff ff ff ff ff de ad be ef 00 00 00 00 |................| 00000010 ff ff ff ff ff ff ff ff 68 65 6c 6c 6f 00 00 00 |........hello...|
参考情報
https://pkg.go.dev/encoding/binary@go1.22.0#Write
https://pkg.go.dev/encoding/binary@go1.22.0#Read
Goのおすすめ書籍
上の書籍の日本語版が下です。
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。