Go言語のencoding/gobは1GBまでのファイルしか読み込めない
結構悩んだのでメモ。あるmap
やslice
など、何かしらのデータの入った変数をファイルとして書き出して、後で利用したいことがたまにあります。
Pythonならpickle
などを使いますが、Go言語ではencoding/gob
という標準ライブラリを使うと似たようなことができるみたいです。
例えば、以下のように書くとmap
をファイルとして保存し、後で読み出せます。
package main import ( "encoding/gob" "log" "os" ) func main() { testmap := map[int]int{ 1: 10, 2: 20, 3: 30, } encodeFile, err := os.Create("test.gob") if err != nil { log.Fatal(err) } defer encodeFile.Close() encoder := gob.NewEncoder(encodeFile) if err := encoder.Encode(testmap); err != nil { log.Fatal(err) } log.Println("Done!") // Decode start newMap := make(map[int]int) decodeFile, err := os.Open("test.gob") if err != nil { log.Fatal(err) } defer decodeFile.Close() decoder := gob.NewDecoder(decodeFile) if err := decoder.Decode(&newMap); err != nil { log.Fatal(err) } log.Println(newMap) // Will print like this: map[3:30 1:10 2:20] }
それはいいのですが、上のコードで言うtestmap
が巨大になると、ファイル生成はされるのですがdecode
でinvalid message length
というエラーが出てうまいこと動きません。(自分の環境では、11000*11000
の行列を入れたら動きませんでした。)
最終的に、encoding/gob
のソースコードを読むことで解決しました。
https://golang.org/src/pkg/encoding/gob/decoder.go
ブログにBSDライセンスの条項どうやって載せるのかわからなかったのでソースコードは載せませんが、要するにオーバーフローしないように読み込むファイルのサイズを1GBに制限するよ!といった内容がコメントで書かれています。
なぜファイル生成はできて読み込みはできないのか(´・ω・`)
中のTODO
コメントでlimit
のコントロールについての言及もあるのですが、今の所Go言語上から制限を外すことはできなさそうです…もしできるのであれば知りたい。あるいは他のもっといい方法があるのでしょうか。
以前も紹介したMarxico
が想像以上に使えますね。ソースコードの整形までやってくれるとは思いませんでした。