3
0

More than 3 years have passed since last update.

Buffer を二回読む必要が生じたら?

Last updated at Posted at 2019-12-24

自分が作っているコマンドで、Buffer を二回読む必要が生じた。Bufferって2回読めたっけ?
と思って、ソースを見てみた。

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
    buf      []byte // contents are the bytes buf[off : len(buf)]
    off      int    // read at &buf[off], write at &buf[len(buf)]
    lastRead readOp // last read operation, so that Unread* can work correctly.
}

プライベートになっていて、アクセス出来ないプロパティがあって、オフセットがあるので、無理っぽい。
オフセットが進んでも、[]byteが変わらなければ、オフセットを元に戻せば良さげだけど、実際は、オフセット
を操作するメソッドは無さげ。

ソースコード

func main() {
    body := &bytes.Buffer{}
    body.WriteString("some string")
    b, err := ioutil.ReadAll(body)
    if err != nil {
        panic(err)
    }

    fmt.Println("1st:" + string(b))

    b, err = ioutil.ReadAll(body)
    if err != nil {
        panic(err)
    }
    fmt.Println("2nd:" + string(b))
}

実行結果

やはり無理でした。

$ go run main.go
1st:some string
2nd:

解決策

Buffer は二回以上読むものではないので、Buffer を2回読む必要があったら、一旦byte に変換すれば簡単でしょう。(追記)下記でコメントをいただきましたが、io.TeeReaderを使う方法でも行けそうです!

func main() {
    body := &bytes.Buffer{}
    body.WriteString("some string")
    b, err := ioutil.ReadAll(body)
    if err != nil {
        panic(err)
    }

    fmt.Println("1st:" + string(b))

    fmt.Println("2nd:" + string(b))

}
$ go run main.go
1st:some string
2nd:some string
3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0