A tour of Go の Flow control statements の exercise
最近インフラ周りでも、golangのOSSが増えてきてコードを読まないといけないことが増えたからgolangのチュートリアルで書き方を覚えようと思い始めた。
exercise-loops-and-functions.go
関数とループを使った簡単な練習として、平方根の計算を実装してみましょう: 数値 x が与えられたときに z² が最も x に近い数値 z を求めるプログラムです。
コード
$ cat exercise-loops-and-functions.go package main import ( "fmt" ) func Sqrt(x float64) float64 { z := 1.0 for i := 0; i < 10; i++ { z -= (z*z - x) / (2*z) } return z } func main() { fmt.Println(Sqrt(2)) }
結果
$ go run exercise-loops-and-functions.go 1.414213562373095
確認
問題文には、「 あなたの関数の結果は標準ライブラリの math.Sqrt にどれくらい近づきましたか?」と書かれていたので、実際に動かしてみる。
$ cat loop-and-functions.go package main import ( "fmt" "math" ) func main() { fmt.Println(math.Sqrt(2)) }
結果
$ go run loop-and-functions.go 1.4142135623730951
答えは1桁多く標準ライブラリの方が多く表示されてるけど、同じと言えるだろう。 ざっくりだけど、他は写経して終わり。
deferがとても新鮮だったような気がする。 deferで定義しておいたprintが最後に評価され、それが出力される。 だから、確実にそのメソッドを終わらせるために定義したい場合に使うのだろうなと思う。 調べてたら、検証している人がいた。
自分でも以下のようなコードで調べてみたら、deferでpanicによるハンドリングができることがわかった。
$ cat recover.go package main import ( "fmt" ) func judge_err() { fmt.Println("judge the error") err := recover() if err != nil { fmt.Println(err) } else { fmt.Println("no error") } } func hello_no_error() { defer judge_err() fmt.Println("Hello World") } func hello_error() { defer judge_err() fmt.Println("Hello World") panic("something error") } func main() { hello_no_error() hello_error() }
これを実行すると、
$ go run recover.go Hello World judge the error no error Hello World judge the error something error
と、一つ目はrecoverで何も入らずno errorが入り、
二つ目はpanicを使っているので、deferで後から評価されsomething error
が出力されていることがわかります。
追記
公式的にもしっかり書いてあった。 Defer, Panic, and Recover - The Go Blog