strconv.Atoiのerrを無視するとゼロ値のまま処理が進む
strconv.Atoiは変換に失敗するとerrを返しますが、これを無視すると1番目の戻り値は黙って0のままになります。エラーチェックをしないと、変換失敗が気づかれずに処理が進んでしまいます。
なぜエラーが出ないのか
出力: 0
(エラーなし)- Goは何も報告しません。コンパイルも実行も正常に終わるコードだからです
出力: 0- 実際の出力 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 package main 2 3 import ( 4 "fmt" 5 "strconv" 6 ) 7 8 func main() { 9 n, err := strconv.Atoi("abc") 10 if err != nil { 11 ^ 12 } 13 fmt.Println(n * 2) 14 }
出力: 0strconv.Atoi("abc")は失敗する
errを無視すると変換失敗に気づけず、nはゼロ値の0のまま計算に使われてしまいます。失敗時はわかりやすい値に倒すべきです。
直し方: (空) を n = -1 にします。
広告
広告スロット(未設定)
パターン2
1 package main 2 3 import ( 4 "fmt" 5 "strconv" 6 ) 7 8 func main() { 9 n, err := strconv.Atoi("xyz") 10 if err != nil { 11 ^ 12 } 13 fmt.Println(n * 3) 14 }
出力: 0strconv.Atoi("xyz")は失敗する
errチェックの中身が空だと、変換に失敗したことに誰も気づかないまま処理が続きます。
直し方: (空) を n = -1 にします。
パターン3
1 package main 2 3 import ( 4 "fmt" 5 "strconv" 6 ) 7 8 func main() { 9 n, err := strconv.Atoi("12x") 10 if err != nil { 11 ^ 12 } 13 fmt.Println(n * 10) 14 }
出力: 0strconv.Atoi("12x")は失敗する
数字混じりの文字列でもAtoiは全体が数値でなければ失敗し、nは0のまま返ります。
直し方: (空) を n = -1 にします。
パターン4
1 package main 2 3 import ( 4 "fmt" 5 "strconv" 6 ) 7 8 func main() { 9 n, err := strconv.Atoi("") 10 if err != nil { 11 ^ 12 } 13 fmt.Println(n * 5) 14 }
出力: 0strconv.Atoi("")は失敗する
空文字列を渡しても変換に失敗しますが、エラーを見ていなければ0が返ったことにしか見えません。
直し方: (空) を n = -1 にします。
パターン5
1 package main 2 3 import ( 4 "fmt" 5 "strconv" 6 ) 7 8 func main() { 9 n, err := strconv.Atoi("one") 10 if err != nil { 11 ^ 12 } 13 fmt.Println(n * 4) 14 }
出力: 0strconv.Atoi("one")は失敗する
errが返ってきた場合にnを明示的なエラー値に倒しておけば、後段の処理で異常だとすぐわかります。
直し方: (空) を n = -1 にします。
よくある誤解
「変換に失敗すればpanicするかプログラムが止まるはず」という思い込みは誤りです。Goのエラーは戻り値として返されるだけで、無視すればプログラムはそのままゼロ値を使って処理を続行します。
まとめ
strconv.Atoiのerrを無視するとゼロ値のまま処理が進むは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。