Golden Road

好きだという熱こそが最低限で最高の希望

bufio.Scannerのエラーと解決策 #golang

こんばんわ。
inabaです。

今日はAtCoder Beginner Contest 055に参加していました。

その時に起こったエラーを調査したので参考までに。

Runtime Error

ある問題を解いて提出したら何件かでRuntime Errorが出た。
Runtime Errorの内容は見られないのでコードをちょこちょこ変えながらデバッグ

原因

読み込み文字列が長いのが原因。
その問題の前提条件には10万文字が最大で入ってくるという事が書いてあったが、bufio.Scannerがデフォルトで最大サイズが決まっている事を知らずハマってた。

最大サイズの定数:

MaxScanTokenSize = 64 * 1024

64 * 1024だから約6万5千文字がデフォルトで読み込める最大文字数。
10万文字なので余裕で超える。
デフォルトを超えるサイズの文字列を(*Scanner).Scanすると(*Scanner).Errbufio.ErrTooLongが返される。

var sc = bufio.NewScanner(os.Stdin)
sc.Split(bufio.ScanWords)
sc.Scan()
if err := sc.Err(); err == bufio.ErrTooLong {
    panic(err)
}

みたいな感じで調査してやっと見つけた。

解決策

(*Scanner).Bufferで最大サイズを指定すると65536文字より大きい文字列も読み込んでくれた。

var sc = bufio.NewScanner(os.Stdin)
sc.Buffer([]byte{}, math.MaxInt64)

こんな感じです。
とりあえずint64の最大値を指定してますが、いきなり指定サイズまでアロケーションされるという事は無く、現行のサイズ*2で読み込みを再試行していくようなのでまぁいいかなと。

src/bufio/scan.go - The Go Programming Language

今日はここまで。