目次
- 概要
- 準備
- ソースコード
- 解説
- ハマったところ
- まとめ
1. 概要
ちょっとしたバイナリファイルを読み込たかったので、
Go言語で実装してみたソースコードを備忘録としてのこしておきます。
ソースコードは下記にあります。
2. 準備
プロジェクトのフォルダ構成は下記のようにしました。
01-read-binary +-- files | +-- OneTwoThree +--- src +--- main +--- main.go
OneTwoThreeは今回読み込むバイナリファイルです。
main.goが実行するGoのソースコードです。
次に読み込むためのバイナリファイルを準備します。
Linuxだとコマンドでバイナリファイルを作成できるようです。
今回は3バイトのバイナリファイルで、順番に1, 2, 3と格納しようと思います。
というわけで下記のコマンドを実行します。
echo -en "\x01\x02\x03" > files/UInt8ArrayOneToThree
3. ソースコード
ソースコード下記の通りです。
package main import ( "encoding/binary" "fmt" "os" ) type ThreeIntegers struct { First uint8 Second uint8 Third uint8 } func main() { readBinaryArray("files/OneTwoThree") } func readBinaryArray(path string) { fmt.Println("readBinaryArray()") file, err := os.Open(path) if err != nil { fmt.Println("error occured 'os.Open()'") panic(err) } var threeIntegers ThreeIntegers errb := binary.Read(file, binary.LittleEndian, &threeIntegers) if errb != nil { fmt.Println("error occured 'binary.Read()'") panic(errb) } fmt.Println("first : ", threeIntegers.First) fmt.Println("second : ", threeIntegers.Second) fmt.Println("third : ", threeIntegers.Third) }
4. 解説
package main
はディレクトリの名前と一致していないといけないです。
import
はvscodeが勝手にやってくれるので、まぁいいですね。
ThreeIntegers
という構造体は uint8
型の1バイトの要素が3つでできます。
os.Open()
でファイルを開きます。
相対パスで指定する場合は go run
を実行した場所からの相対パスになります。
binary.Read()
でバイナリファイルを読み込んで、内容を構造体に詰めます。
最後に構造体の内容を標準出力に出力しています。
5. ハマったところ
上記のソースコードに至るまえにはまったのが次のエラー。
panic: reflect: reflect.Value.SetUint using value obtained using unexported field goroutine 1 [running]: reflect.flag.mustBeAssignable(0x1aa) /Users/shogo/.goenv/versions/1.11.4/src/reflect/value.go:231 +0x1ee reflect.Value.SetUint(0x10a5940, 0xc000090000, 0x1aa, 0x61616161) /Users/shogo/.goenv/versions/1.11.4/src/reflect/value.go:1551 +0x2f encoding/binary.(*decoder).value(0xc000076e78, 0x10a5940, 0xc000090000, 0x1aa) /Users/shogo/.goenv/versions/1.11.4/src/encoding/binary/binary.go:552 +0x8ac encoding/binary.(*decoder).value(0xc000076e78, 0x10aff60, 0xc000090000, 0x199) /Users/shogo/.goenv/versions/1.11.4/src/encoding/binary/binary.go:523 +0x2c5 encoding/binary.Read(0x10dc060, 0xc000086018, 0x10dc440, 0x1187f88, 0x10a08c0, 0xc000090000, 0xc00008c000, 0xc000076f18) /Users/shogo/.goenv/versions/1.11.4/src/encoding/binary/binary.go:248 +0x342 main.readBinaryArray(0x10ca1bc, 0x1a) /Users/shogo/prg/github/go-sample/01-read-binary/src/main/main.go:25 +0x124 main.main() /Users/shogo/prg/github/go-sample/01-read-binary/src/main/main.go:14 +0x36 exit status 2
エラーメッセージを読んでもさっぱり分からなかったですが、
調べてみたら構造体のフィールド名が public
なのに小文字から始まっていたからでした。
type ThreeIntegers struct { first uint8 second uint8 third uint8 }
正しくは下記。
type ThreeIntegers struct { First uint8 Second uint8 Third uint8 }
6. まとめ
ちょっとしたバイナリを読み込むにはC/C++より手軽に実装できてよかったです。
気に入ったのは、vscodeがとにかくいろいろ補完が気がきくとこでした。
コードを書いている時のストレスはかなり少なかったと思います。
これからも使えそうな場所ではどんどんGoを使っていきたいと思います。