【Golang】gobで変数をファイルに保存する

gobは、Go専用のバイナリシリアライズフォーマットです。 シリアライズフォーマットとしては、Protocol Buffers1デファクトでしょうし、Go専用のgobは他の言語で扱えず、使い勝手としても難しいところです。 しかし、Goしか使っていないような環境で、変数をファイルに保存したい場合などでは便利なので、備忘メモとしてもまとめたいと思います。

考え方は、Gobs of data - The Go Blogencoding/gobでinterface{}をシリアライズする がとても参考になりました。

また、Redditでも議論されているように、structのsliceをdeep copyしたいときの手段としてgobが有用そうです。

概要

gobは、encoding/gobに標準パッケージとして用意されています。 使う際も NewEncoder(w io.Writer)NewDecoder(r io.Reader)が用意されているので、jsonを扱うときと同じ要領で扱うことができます。

今回は、以下で定義したPerson型の変数をファイルへ保存、ファイルから復元してみます。

type Person struct {
    Name string
    Age  int
}

ファイルへ保存

package main

import (
    "encoding/gob"
    "log"
    "os"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{
        "Alice",
        20,
    }

    f, err := os.Create("./save.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()
    enc := gob.NewEncoder(f)

    if err := enc.Encode(p); err != nil {
        log.Fatal(err)
    }
}

ファイルから復元

package main

import (
    "encoding/gob"
    "fmt"
    "log"
    "os"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    f, err := os.Open("./save.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    var q Person
    dec := gob.NewDecoder(f)
    if err := dec.Decode(&q); err != nil {
        log.Fatal("decode error:", err)
    }

    fmt.Println(q) // {Alice 20}
}

References


  1. (2018/03/11)投稿時は、gRPCと記載していましたが、シリアライズフォーマットとしてはProtocol Buffersが正しいため訂正します。