この記事を公開したときの私の第一印象をよく覚えています。 これは次のようなものでした。 「ここでは奇妙な例が選ばれました。例外を除いてコードがより簡潔になることは明らかです。 例外なく、どうにかしてそれを減らすことができる言い訳をする試みのように見えます 。 私は例外のファンではなかったという事実にもかかわらず、記事で説明されている例は、この比較を直接求めました。 「エラーは意味である」というフレーズでパイクが言いたかったことはあまり明確ではありませんでした。
同時に、重要なものが欠けていることに気づいたので、読んだものを吸収するために少し時間をとりました。 そして、ある時点で、記事に戻って、理解は自然に生まれました。
Goは、プログラマーにエラーと他のコードを処理するように依頼します。 彼は、エラーを特別なアプローチ/ツール/パターンを必要とする特別なエンティティと見なすのではなく、プログラムの通常のロジックを解釈するのと同じ方法でエラー処理コードを解釈するよう求めます。 エラー処理コードは特別な構造ではなく、他のすべてのユーザーと同様に、コードの本格的な部分です。
変数、条件、意味など、通常の言語構成要素について話している場合、あなたの考えがどうなるか想像してみてください。 -そしてそれらをエラー処理に適用します。 それらは同じレベルのエンティティであり、ロジックの一部です。 関数の戻り値を特別な理由もなく無視しないのですか? ifが退屈すぎるので、ブール値を扱う特別な方法を言語に要求しないでください。 「このネストレベルでsqrt関数の結果をどう処理するかわからない場合はどうすればよいですか」と混乱することはありません。 必要なロジックを記述するだけです。
繰り返しますが、エラーは一般的な意味であり、エラー処理は通常のプログラミングとまったく同じです。
元の記事の例に似た例でこれを説明してみましょう。 「繰り返しエントリをいくつか作成し、書き込まれたバイト数をカウントし、1024バイト後に停止する」というタスクがあるとします。 額の例から始めます。
var count, n int n = write("one") count += n if count >= 1024 { return } n = write("two") count += n if count >= 1024 { return } // etc
play.golang.org/p/8033Wp9xly
, , . , DRY, :
var count int cntWrite := func(s string) { n := write(s) count += n if count >= 1024 { os.Exit(0) } } cntWrite("one") cntWrite("two") cntWrite("three")
play.golang.org/p/Hd12rk6wNk
, , . os.Exit , … ? — , , , , . writer- :
type cntWriter struct { count int w io.Writer } func (cw *cntWriter) write(s string) { if cw.count >= 1024 { return } n := write(s) cw.count += n } func (cw *cntWriter) written() int { return cw.count } func main() { cw := &cntWriter{} cw.write("one") cw.write("two") cw.write("three") fmt.Printf("Written %d bytes\n", cw.count) }
play.golang.org/p/66Xd1fD8II
— writer , , . , , .
«counter» «error value» -- . , . «» , «» 1024 — .
— — « » « », . , - , . , .
, , , . - , Go , , , . , — .
, . . Go , . , , , , . , , .
— « » — .
PS. .