takuroooのブログ

勉強したこととか

Go strings/Reader

strings.Readerを触ってみた。

golang.org

目次

NewReader

strings.Readerのポインタを生成する。

reader := strings.NewReader("abcdef")
fmt.Printf("%T %v\n", reader, reader) // *strings.Reader &{abcdef 0 -1}

ちなみにここで生成されるstrings.Readerはio.Readerというinterfaceの定義を満たしているので、io.Readerとして扱うことができる。

type Reader interface {
    Read(p []byte) (n int, err error)
}

strings.Readerはこんな感じのパラメータを持っている。

type Reader struct {
    s        string
    i        int64 // current reading index
    prevRune int   // index of previous rune; or < 0
}

Read

現在のリードインデックスの位置から終端までの文字列をリードする。

var n int
var err error
reader := strings.NewReader("abcdef")

buf := make([]byte, reader.Size())
n, err = reader.Read(buf)
fmt.Println(string(buf), len(buf), n, err) // abcdef 6 6 <nil>
  • 引数で渡しているbufにリードした文字列が格納される。
  • 戻り値としてリードした文字数とエラーの内容を返す。
  • もう一回Readを呼ぶとerrio.EOFが返ってくる。

ReadAt

指定したリードインデックスから終端までの文字列をリードする。

var n int
var err error
reader := strings.NewReader("0123456")
buf := make([]byte, reader.Size())
n, err = reader.ReadAt(buf, 2)
fmt.Println(string(buf), len(buf), n, err) // 23456 7 5 EOF
  • (なぜか)Readと違ってリードして終端までいったらすぐにEOFを返す。

ReadByte

1バイトずつリードする。

var b byte
var err error
reader := strings.NewReader("12")
b, err = reader.ReadByte()
fmt.Println(string(b), err) // 1 <nil>
b, err = reader.ReadByte()
fmt.Println(string(b), err) // 2 <nil>
b, err = reader.ReadByte()
fmt.Println(string(b), err) //   EOF

Reset

リーダーが内部に持つ文字列を初期化する。

var b byte
var err error
reader := strings.NewReader("12")

reader.Reset("ab")
b, err = reader.ReadByte()
fmt.Println(string(b), err) // a <nil>
b, err = reader.ReadByte()
fmt.Println(string(b), err) // b <nil>
  • 引数で受け取った文字列で内部で新しくstrings.Readを作っている。

Len/Size

var n int
var err error
reader := strings.NewReader("abcdef")
fmt.Printf("%T %v\n", reader, reader) // *strings.Reader &{abcdef 0 -1}
buf := make([]byte, reader.Size())

fmt.Println(reader.Len(), reader.Size()) // 6 6

n, err = reader.Read(buf)
fmt.Println(string(buf), len(buf), n, err) // abcdef 6 6 <nil>

fmt.Println(reader.Len(), reader.Size()) // 0 6

n, err = reader.Read(buf)
fmt.Println(string(buf), len(buf), n, err) // abcdef 6 0 EOF
  • Sizeはreaderが保持している文字列全体のサイズ。常に同じ値を返す。
  • Lenは現在のリードインデックスから終端までのサイズ。

Seek

リードインデクスの位置を操作する。

var b byte
var err error
reader := strings.NewReader("012345")

reader.Seek(1, io.SeekStart)
b, err = reader.ReadByte()
fmt.Println(string(b), err) // 1 <nil>

reader.Seek(1, io.SeekCurrent)
b, err = reader.ReadByte()
fmt.Println(string(b), err) // 3 <nil>

reader.Seek(-1, io.SeekEnd)
b, err = reader.ReadByte()
fmt.Println(string(b), err) // 5 <nil>
  • 他の言語でもよくあるseek関数と同じようなもの。
  • io.SeekEndを使うときはリードインデックスはマイナス値で指定する。