😇

GoのREPL gore で panic を起こすとそれしか出力されない

commits1 min read

TL;DR

  • motemen/gore で一度panicが起きるようなコードを書いてしまうと、以降ずっと同じpanicが吐かれる
  • 起きてしまったらどうしようもないので、 :clear しましょう

goreでpanicを起こすとこうなる

このように出力されます。

// "hoge" を出力する
gore> _, _ = fmt.Println("hoge")
hoge

// panicを起こす
gore> panic("panic")
hoge
panic: panic

goroutine 1 [running]:
main.main()
+0x95
exit status 2

// "fuga" を出力する
gore> _, _ = fmt.Println("fuga")
hoge
panic: panic

goroutine 1 [running]:
main.main()
+0x95
exit status 2
// fugaは出力されない!

一度panicを起こすとそれ以降のコードは実行されないようです。

なぜこんなことが起きるのか

README.md にその理由となる挙動について書いてあります。

gore runs code using go run for each input. All the inputted lines are evaluated again and again...

motemen/gore: Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.

日本語にすると以下の通りです。

goreは入力のたびにコードを go run で実行する。すべての入力された行は都度再計算される。

したがって、一旦panicしてしまうと、以降入力したコードはそのpanicを実行するせいで棄却されてしまい、だから出力内容は常に同じpanicになる、ということのようです。

つまり、goreでpanicを起こすとこうなっている

以上で完全にわかったようなものですが、ダメ押しで実際にどんな挙動をしているかを確認してみます。

先ほどの「goreでpanicを起こすとこうなる」の例で、入力とgore内部で実行されるコードを列挙します。

  1. _, _ = fmt.Println("hoge") を入力
    • func main() { _, _ = fmt.Println("hoge") } が実行される
  2. panic("panic") を入力
    • func main() { _, _ = fmt.Println("hoge"); panic("panic") } が実行される
  3. _, _ = fmt.Println("fuga") を入力
    • func main() { _, _ = fmt.Println("hoge"); panic("panic"); _, _ = fmt.Println("fuga") } が実行される

こうしてみると、3で入力された部分は出力されないのも当然ですね。

どうすればpanicを吐くコードを取り消せるのか

現状ではできないようです。

:clear してはじめからやり直しましょう。

おわりに

公式ドキュメントを読みましょう。

GitHubで編集を提案

Discussion

ログインするとコメントできます