goでAtCoder(競技プログラミング)を始めたところVSCodeでのデバッグでつまづいたのでメモ.
経緯
コードが期待通り動かない
→ 変数を追いながらdebugしたい
→ delveは標準入力を受け付けられない
→ testファイル内でos.Stdinをスタブし, bufio.NewScannerを再定義して解決
Sample Code
回答用コード.
struct IO に 各種input/output用の関数を実装する.
デフォルトでは標準のbufio.Scannerでstdinをinput.
main.go
package main
import (
"bufio"
"fmt"
"os"
)
type IO struct {
scanner *bufio.Scanner
writer *bufio.Writer
}
func newIO() *IO {
return &IO{
scanner: bufio.NewScanner(os.Stdin),
writer: bufio.NewWriter(os.Stdout),
}
}
func (io *IO) nextLine() string {
io.scanner.Scan()
return io.scanner.Text()
}
func (io *IO) nextInt() int {
i, e := strconv.Atoi(io.nextLine())
if e != nil {
panic(e)
}
return i
}
func (io *IO) printLn(a ...interface{}) {
fmt.Fprintln(io.writer, a...)
}
var io = newIO()
func main() {
io.scanner.Split(bufio.ScanWords) // switch to separating by space
io.scanner.Buffer([]byte{}, 100000007) // switch to read large size input
defer io.writer.Flush()
N := io.nextInt()
hoge := someProcess(N)
io.printLn(hoge)
}
デバッグ用コード.
Stdinをstubしてio.scannerを上書き.
./stdin.txt
から入力を読み取りmain()を実行する.
main_test.go
package main
import (
"bufio"
"io/ioutil"
"os"
"testing"
)
func TestAnswer(t *testing.T) {
inbuf := readFile("./test.txt")
stubStdin(inbuf, func() {
main()
})
}
func readFile(fileName string) string {
bytes, err := ioutil.ReadFile(fileName)
if err != nil {
panic(err)
}
return string(bytes)
}
// Stubs Stdin in 'fn'
func stubStdin(inbuf string, fn func()) {
inr, inw, _ := os.Pipe()
_, _ = inw.Write([]byte(inbuf))
inw.Close()
os.Stdin = inr
io.scanner = bufio.NewScanner(os.Stdin)
fn()
}