golangのpanicは例外ではないのか?

goには例外がないと言われている.確かに,よく見かける,exception とかはないんだけど,あれ? panic があるじゃん?

では panic は例外ではないのか?

我々は、処理構造を制御するためのtry-catch-finally形式の例外処理機構によって、コードが入り組んでしまうと考えています。しかも、ファイルを開けないといった、ごく一般的なエラーをさも特別なエラーであるかのように扱わせる傾向があります。

Go言語では、異なるアプローチを取りました。Go言語では戻り値として複数の値が返せるので、一般的なエラーハンドリングの場合、戻り値といっしょにエラー情報を返すことができます。エラー型は標準化されており、Goの他の機能と相まってエラーハンドリングがすっきりしたものとなります。これは、他の言語と大きく異なる点です。

それとは別に、Go言語にはエラーシグナルの発行機構と、本当に例外的な状況から回復する機構があります。エラーの発生によって、関数のコールスタックの巻き戻りが開始する中でのみ、このエラー回復メカニズムは実行可能です。このメカニズムは、大きな障害をハンドリングするのにも充分な上に、処理構造に特別な制御を行う必要もありません。また上手に使えば、エラーハンドリングのコードが読みやすくもなります。

http://golang.jp/go_faq

つまり,try-catch-finally形式の例外ではない.

冒頭でも述べたように、Goは一般的な例外処理への使用を推奨しないものの、例外処理用の専用構文を備えている。一般的な例外にはあくまで戻り値を使う。

https://ja.wikipedia.org/wiki/Go_%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%29#.E4.BE.8B.E5.A4.96.E5.87.A6.E7.90.86

なるほど.ということは,「例外が存在しない」わけではなくて「一般的なtry-catchの中で発生させているような使い勝手の良いexceptionがない」というべきなのか.

厳密に言えば,panic defer recoverpanic を拾えるわけだ.ただし,ブロックのようなものを作れないので,あくまで関数全体に対して,defer recover することにはなるのだが. ただ,その機構を いつものexception みたいに使うなよ っていう意味を込めての「例外がない」なのか.

とはいえ,実現したいことは理解できる.

一般的な,try-catch内で発生させる exception については,「それ本当に例外なのか?」というのと「読みにくい」に尽きる. そこに関しては納得できる.

ただ,例外を使わずこまめに error を返していくと,こういう意見にも納得できるわけで…….

if err != nil によるエラーハンドリングを繰り返し繰り返し書かなくてはならないことがあります。 Go Blogにはif err != nil { return err }のパターンはあまり出現しない(once per page or two)と書かれていますが、 プログラムのタイプによっては(例えばいろいろな外部リソースや外部ライブラリをつなぐようなコード)かなりの頻度で if err != nil を書かざるを得ないことがあるような気がします。

http://www.yunabe.jp/docs/golang_pitfall.html#section-4

さらに,この error を書くパターンだと,スタックトレースを見るために発生源の情報を error に追記する必要があり…….

これでエラーがどこで発生したのかが分かるようになります。ただこういうことしてると実は例外で良かったんじゃないかという気分にもなりますが。

http://www.yunabe.jp/docs/golang_pitfall.html#return-nil-err--error

なので,結局割といっぱいこのパターンを書かなきゃいけないとは思うんですよね.

ただ,最初の思惑どおり,やっぱり例外として既に別処理に回されたりしていることはないので,上から順番に処理されていくという意味で読みやすくはあります.