- 既存のライブラリに bufio.Scanner があるが、改行をカットしてしまう
- 改行を含めて読み取りたいときは
(*bufio.Reader) ReadString('\n')
を使う- EOF を検出した時の処理が面倒だが、雑に書くと最終行が失われてしまう
面倒なく、ありのままに読み込むコードを楽に書くための iterator を書いた
foo.go
package main import ( "bufio" "fmt" "io" "os" ) func readlines(r io.Reader) func(func(string, error) bool) { return func(yield func(string, error) bool) { var br *bufio.Reader if _br, ok := r.(*bufio.Reader); ok { br = _br } else { br = bufio.NewReader(r) } for { line, err := br.ReadString('\n') if err != nil && err != io.EOF { yield(line, err) return } if !yield(line, nil) { return } if err == io.EOF { return } } } } // 以上がライブラリコード // 以下、使用例 func mains() error { for line, err := range readlines(os.Stdin) { if err != nil { return err } fmt.Print(line) } return nil } func main() { if err := mains(); err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } }
サンプルファイル foo.txt (制御コードが分かるよう、バイナリエディターのアウトプットで)
$ binview.exe foo.txt binview snapshot-windows-amd64 by go1.17.7 00000000 41 42 43 0D 0A 44 45 46 0D 0A 47 48 49 ABC←↓DEF←↓GHI [UTF8] 70='\x46'(1/1:U+0046) @ 7=0x7/13=0xD
実行結果:
[1] <DESKTOP-NPOTG52:~> $ env GOEXPERIMENT=rangefunc go run foo.go < foo.txt ABC DEF GHI[1] <DESKTOP-NPOTG52:~> $