読者です 読者をやめる 読者になる 読者になる

隙あらば寝る

うぇぶのかいしゃではたらくえんじにあがかいています

golang json decoder and eof

tl;dr;

json.Decoder は EOF を検出するとその後 decode を行わなくなる。

この挙動は tail しつつデコードを続けるような要件と合わない。

詳細

ファイルを tail しつつ、1行毎に json が追記されるようフォーマットを decode したいと考えていた。

以下の様なコードを書くイメージ。

f, _ := os.Open("./file.json")
dec := json.NewDecoder(f)
v := SomeStruct{}
for {
  dec.Decode(&v)
}

しかし json.Decoder は一度末尾まで到達し EOF を検出すると、内部でエラーが発生したことを覚えているため、その後デコードしなくなってしまう。

つまり追記分が一切デコードされなかった。

読み込み部分は自作する必要がありそうなので以下のようなコードを書いて解決した。

これもイメージ、コンパイルは通らないが処理の内容は伝わると思う。

(実際には ReadLine の prefix とか見ないとダメだが長くなるので省略した)

f, _ := os.Open("./file.json")
r := bufio.NewReader(f)
v := SomeStruct{}
var buf bytes.Buffer
for {
  l, _, err := r.ReadLine()
  if err != nil{
    if err == io.EOF{
      // 追記待ちでビジーループするので適当に sleep する
      time.Sleep(time.Second) 
      continue
    }
    return err
  }
  json.Unmarshal(l, &v)
}

これで追記されていくファイルを tail しながら、内容の json をデコードできる。