全力で怠けたい

怠けるために全力を尽くしたいブログ。

プログラムのちょっとした動作を確認するときはシェルが役に立つメモ。

Go を勉強している人が「Go の bufio パッケージのScanner.Err() に non nil の error を返させたい」と言ってたのでシェルを使ったら簡単にやれますよ、と話をしたときのメモ。

相手の人が書いてた Go のプログラムはこんな感じ。

// main.go
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)

    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "failed to Scanner.Scan(): ", err)
    }
}

Scanner.Scan() で標準入力を読んだのをそのまま標準出力にプリントするプログラムなんだけど fmt.Fprintln(os.Stderr, "failed to Scanner.Scan(): ", err) のところを動かしてみたいらしい。

こういうのはシェルを使うと簡単に目的を達成できる。

これだけ。

$ yes | head -n 65536 | tr -d '\n' | go run main.go > /dev/null
failed to Scanner.Scan():  bufio.Scanner: token too long

# Go コードへの入力が1バイト少ないときはエラーにならないでちゃんと動く
$ yes | head -n 65535 | tr -d '\n' | go run main.go > /dev/null

ちなみに ↑ で 65536 バイトを指定するとエラーになるのは標準出力から Go コードへの入力が bufio/scan.goMaxScanTokenSize 以上にになってしまうため。

// bufio/scan.go
    MaxScanTokenSize = 64 * 1024

func (s *Scanner) Scan() bool {
// 省略
            if len(s.buf) >= s.maxTokenSize || len(s.buf) > maxInt/2 {
                s.setErr(ErrTooLong)
                return false
            }