Go言語で以下の頻出操作を行うスニペットを書いた。
- ファイルをバイト列として読む
- ファイルの内容をチャンネルで別のゴルーチンに渡す(そこで標準出力する)
- チャンネルのクローズを検出しゴルーチンの終了処理を適切に行う
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
)
func main() {
flag.Parse()
in_file := flag.Arg(0)
f, e := os.Open(in_file)
if e != nil {
log.Fatal(e)
}
defer f.Close()
ch := make(chan []byte)
done := make(chan struct{})
// 標準出力用ゴルーチン起動
go func() {
loop:
for {
select {
case b, ok := <-ch:
if !ok { // selectでchanのクローズを検知する方法
fmt.Println("ch is closed")
break loop
}
fmt.Println(b)
}
}
fmt.Println("End of goroutine")
done <- struct{}{}
}()
// ファイルRead用forループ
for {
buf := make([]byte, 32)
if n, e := f.Read(buf); e != nil {
if e != io.EOF {
log.Fatal(e)
}
break
} else {
ch <- buf[0:n]
}
}
close(ch) // ファイル終端でchをcloseする
// 非同期に実行されているゴルーチンの終了を待つ。
<-done
fmt.Println("End of main")
}
$ go run main.go ./test.txt
[158 224 103 77 111 33 95 39 188 146 170 235 91 131 179 220 242 230 54 155 28 133 74 173 244 247 31 51 64 3 46 156]
[39 169 91 192 127 169 65 225 11 114 59 49 216 115 158 55 93 79 55 47 160 40 233 23 131 217 80 41 92 149 101 103]
[218 177 14 79 225 93 123 229 14 65 68 242 84 59 118 198 52 73 215 50 136 189 20 225 87 240 156 178 175 85 102 45]
[34 124 209 135 158 151 224 165 7 3 209 220 45 87 47 115 123 98 32 10 217 172 149 26 41 78 88 186 116 87 251 218]
ch is closed
End of goroutine
End of main