Pro Yearly is on sale from $80 to $50! »

Why should we use bufio.ReadBytes, ReadString instead of ReadSlice in most cases?

Why should we use bufio.ReadBytes, ReadString instead of ReadSlice in most cases?

#fukuokago の Lightning Talk資料です。

Google Slide is here https://docs.google.com/presentation/d/1Q_HpKo0zqYSMTietQrQatOEjVutkIyyLUDzQNRukJFg/edit?usp=sharing .

88964b936e864ca7d326272eaa70fa9a?s=128

Kazuki Higashiguchi

July 14, 2020
Tweet

Transcript

  1. Why should we use bufio.ReadBytes, ReadString instead of ReadSlice in

    most cases? fukuoka.go, JULY 14 2020 #ちょっと深堀り #コードリーディング #社内でGophersCodeReadingPartyはじめました #fukuokago Presented by @hgsgtk
  2. { About me GitHub/Twitter: @hgsgtk BASE BANK, Inc. (BASE, Inc.)

    東京からお邪魔してます #fukuokago
  3. #社内でGophersCodeReadingPartyはじめました • 有志でゆるくやっている の勉強会 • 気になる のあの挙動「どう実装されてるの?」を実装で追っ ていって、最終的に勉強になってしまう会 • 事前準備なし、気になるツール・ライブラリの中身を、読んで

    みる • 週
  4. #社内でGophersCodeReadingPartyはじめました #社内でGophersCodeReadingPartyはじめました mackerelio/mackerel-agent-plugin GoogleCloudPlatform/terraformer Songmu/kibelasync terraform-providers/terraform-provider-aws kayac/ecspresso hashicorp/terraform mackerelio/mkr

  5. パーティ中の一コマ... この bufio パッケージの説明どういうこ とだろう...?

  6. “Because the data returned from ReadSlice will be overwritten by

    the next I/O operation, most clients should use ReadBytes or ReadString instead.” godoc.org bufio package func (*Reader) ReadSlice https://godoc.org/bufio#Reader.ReadSlice
  7. “ReadLine is a low-level line-reading primitive. Most callers should use

    ReadBytes('\n') or ReadString('\n') instead or use a Scanner.” godoc.org bufio package func (*Reader) ReadLine https://golang.org/pkg/bufio/#Reader.ReadLine
  8. #ちょっと深堀り • の仕様・ ユーザーとしての使い方 • の関係性 • が内部実装で何をやってくれているか

  9. ReadSlice の仕様 戻り値が上書きされる例 #1 https://play.golang.org/p/Drl1FjauMeM (Copyright: 同僚の @budougumi0617 さんの再現コード) ←

    1. buffer から読み取る ← 2. 内部の buffer が上書きされるような操作をする ← 3. 再度 “1.” で取得した値を表示 4. ReadSlice の場合は、元のbufferのsliceの ため、 bufferの上書きにより、中身が変わっている
  10. ReadSlice の仕様 戻り値が上書きされる例 #2 https://play.golang.org/p/BRhnRMsFa59 ← 1. buffer から読み取る ←

    2. 内部の buffer が上書きされるような操作をする ← 3. 再度 “1.” で取得した値を表示 4. ReadSlice の場合は、元のbufferのsliceの ため、 bufferの上書きにより、中身が変わっている
  11. “ReadSlice reads until the first occurrence of delim in the

    input, returning a slice pointing at the bytes in the buffer.” godoc.org bufio package func (*Reader) ReadSlice https://godoc.org/bufio#Reader.ReadSlice → 戻り値は、bufferのsliceなので後続のbufferへの操作で中身が変わる
  12. ReadBytes, ReadString, ReadSlice, ReadLine の関係性 Reader.ReadString(delim byte) (string, error) Reader.ReadBytes(delim

    byte) ([]byte, error) Reader.ReadSlice(delim byte) ([]byte, error) call call → を使用すべきなのはなぜ? Reader.ReadLine() ([]byte, bool, error) call
  13. ReadString -> ReadBytes https://golang.org/src/bufio/bufio.go?s=11350:11404#L474 func (b *Reader) ReadString(delim byte) (string,

    error) { bytes, err := b.ReadBytes(delim) return string(bytes), err } ReadString は ReadBytes の戻り値 []byte を string 型に変換するだけ
  14. ReadBytesが内部実装で何をやってくれているか https://golang.org/src/bufio/bufio.go?s=11350:11404#L419 ← ReadSlice を call ← !! 新たなバッファを用意し値をコピー そのため、もともとのバッファに対するI/O操作の

    影響を受けなくなる
  15. slice の 配列ポインタを比較してみる https://play.golang.org/p/Vom_IJf8Ua7 ← 1. もともとの[]byte の .pointer ←

    2. ReadSlice / ReadBytes で取得し た []byte の .pointer ↓ 3. ReadSlice は同じアドレス ReadBytes の場合は違うアドレスと なってる
  16. “in most cases” に当てはまらないときって? • メモリ使用量が気になるケースで、 の 使用に利点がありそう • For

    many applications, a single line is sufficient: hence, some commenters suggested ReadLine() or something similar.
  17. まとめ #ちょっと深堀り • の戻り値は、 の なので後 続の への操作で中身が変わる • では、コピーしているため、元のバッファに対する

    オペの影響を受けない • メモリ効率が気になる場合だと、 を用 いるという判断もありそう
  18. まとめ #社内でGophersCodeReadingPartyはじめました • 業務ではスルーしがちな、細かい標準パッケージ、中を見る いい機会になる • 身近な興味のあるツールやライブラリを起点にすると、ユース ケースをイメージしやすい • 時代に、他チームとのコミュニケーションの機会になって

    良いという声も