このエラーが発生する理由
Goの開発者は、文字列を整数に変換する際に strconv.Atoi: parsing invalid syntax エラーに頻繁に遭遇します。これは strconv.Atoi が厳格であるために起こります。この関数は、きれいな10進数の数字のみで構成された文字列を想定しています。文字列にそれ以外のもの(たった1つの隠れたスペースであっても)が含まれている場合、関数は数値ではなくエラーを返します。
主な原因
実際に失敗を引き起こしている原因は何でしょうか?単に "abc" のようなランダムな文字列であることは稀で、通常はより微妙な原因が潜んでいます。
- 隠れた空白文字:
os.Getenvやr.FormValueから取得した文字列には、目に見えない\n、\r、またはスペース(例:" 42 ")が含まれていることがよくあります。 - フォーマットされた数値: カンマ(
"1,250")や通貨記号を含む数値は失敗します。 - 空の入力: 空の文字列
""をパースしようとすると、まさにこのエラーが発生します。 - 小数点:
strconv.Atoiは"99.9"を処理できません。整数のみを理解します。
解決方法
1. まず文字列をクリーンアップする
ほとんどのバグは、入力をトリミングするだけで解消されます。strings パッケージを使用して、ターミナルや設定ファイルから混入した可能性のある改行やスペースを取り除きます。
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// スペースと改行が含まれる典型的な乱れた入力
input := " 1024 \n"
// クリーンアップする
cleanInput := strings.TrimSpace(input)
num, err := strconv.Atoi(cleanInput)
if err != nil {
fmt.Printf("変換に失敗しました: %v\n", err)
return
}
fmt.Println("変換後の値:", num)
}
2. エラーを適切に処理する
アンダースコア(_)を使ってエラーを無視してはいけません。strconv.Atoi が失敗すると、結果として 0 を返します。エラーを無視すると、ロジックにそぐわないゼロ値のまま処理が進んでしまう可能性があります。
val, err := strconv.Atoi(userInput)
if err != nil {
// クラッシュの原因となった特定の入力をログに出力
fmt.Printf("エラー: '%s' は有効な整数ではありません\n", userInput)
return
}
3. 小数点への対処
データソースから "100.00" のような数値が送られてくる場合、Atoi はそれらを拒否します。最善の方法は、まず浮動小数点数としてパースし、精度を落とす必要がある場合に整数に変換することです。
input := "123.45"
f, err := strconv.ParseFloat(input, 64)
if err == nil {
i := int(f) // 123に切り捨て
fmt.Println("整数の値:", i)
}
4. 正規表現によるガードを使用する(任意)
処理の前に文字列が厳密に数値であることを検証する必要がある場合は、正規表現による素早いチェックが役立ちます。
import "regexp"
// 正および負の整数に一致
var isInt = regexp.MustCompile(`^-?\d+$`)
func isValid(s string) bool {
return isInt.MatchString(s)
}
修正のテスト
以下のテストループを実行して、ロジックがさまざまなシナリオを正しく処理できるか確認してください。
testInputs := []string{"77", " -42 ", "1.5", "abc"}
for _, str := range testInputs {
clean := strings.TrimSpace(str)
n, err := strconv.Atoi(clean)
if err != nil {
fmt.Printf("失敗: [%s] -> %v\n", str, err)
} else {
fmt.Printf("成功: [%s] -> %d\n", str, n)
}
}
プロのヒント
- ビットサイズに注意: 大きな数値を扱う場合は、32ビットシステムでのオーバーフローを避けるために
strconv.ParseInt(s, 10, 64)を使用してください。 - デフォルト値の設定: パースに失敗したときのフォールバック値を決めておきましょう。
0を返すのが適切な場合もあれば、処理を完全に停止させる必要がある場合もあります。 - 入力の標準化: データソースを制御できる場合は、カンマや通貨記号を含まない生の数字のみを送信するように徹底してください。

