- 既存のライブラリに 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:~>
$