Как преобразовать строку в число (int) в Go? Обработка ошибок и примеры
Использование пакета strconv для преобразования строки в число
В Go нет встроенного приведения типов между строкой и числом (как в Python или JavaScript). Для этой задачи существует стандартный пакет strconv (string conversion). Основная функция — strconv.Atoi() (ASCII to Integer), которая преобразует строку в int.
Базовый пример: strconv.Atoi()
package main
import (
"fmt"
"strconv"
)
func main() {
str := "42"
num, err := strconv.Atoi(str)
if err != nil {
fmt.Println("Ошибка преобразования:", err)
return
}
fmt.Printf("Число: %d, тип: %T\n", num, num) // Число: 42, тип: int
}
Почему функция возвращает два значения?
В Go принято возвращать ошибку как второе значение. Если строка не является валидным числом (например, содержит буквы), err будет не nil, а num получит нулевое значение (0). Это заставляет разработчика явно обрабатывать ошибочные ситуации.
Исправленный калькулятор
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: calculator <num1> <num2>")
return
}
a, err1 := strconv.Atoi(os.Args[1])
b, err2 := strconv.Atoi(os.Args[2])
if err1 != nil || err2 != nil {
fmt.Println("Ошибка: оба аргумента должны быть целыми числами")
return
}
sum := a + b
fmt.Printf("Сумма: %d\n", sum)
}
Альтернативы: strconv.ParseInt() и strconv.ParseFloat()
Если вам нужно контролировать разрядность (int32, int64) или основание системы счисления (2, 8, 10, 16), используйте ParseInt():
// Преобразование строки в int64 с основанием 10
str := "255"
num64, err := strconv.ParseInt(str, 10, 64)
if err != nil {
panic(err)
}
fmt.Printf("int64: %d\n", num64)
// Для чисел с плавающей точкой — ParseFloat()
floatStr := "3.14"
f, err := strconv.ParseFloat(floatStr, 64)
if err != nil {
panic(err)
}
fmt.Printf("float64: %f\n", f)
Разница между int и int64
int— платформозависимый тип: 32 бита на 32-разрядных системах, 64 бита на 64-разрядных.int64— всегда 64 бита. Используйте его, если нужно гарантировать размер.Atoi()возвращаетint. Если вам нуженint64, используйтеParseInt(str, 10, 64).
Обработка ошибок: подробнее
Не игнорируйте ошибку через _ (подчёркивание) — это может привести к незаметным багам. Правильный паттерн:
num, err := strconv.Atoi(input)
if err != nil {
// Логируем, выводим пользователю сообщение или используем значение по умолчанию
fmt.Printf("Некорректный ввод '%s': %v\n", input, err)
return
}
// Работаем с num
Проверка на пустую строку
Пустая строка также вызовет ошибку. Если вы ожидаете, что строка может быть пустой, проверяйте длину перед преобразованием:
if input == "" {
// Обработка пустого значения
num = 0
} else {
num, err = strconv.Atoi(input)
}
Таким образом, strconv.Atoi() — самый простой и безопасный способ преобразовать строку в int в Go. Всегда обрабатывайте ошибку, и ваш код будет надёжным.
Использование fmt.Sscanf() для парсинга чисел из строк
Иногда удобно использовать функцию fmt.Sscanf(), особенно если строка содержит несколько значений или имеет сложный формат. Она работает как scanf из C.
package main
import (
"fmt"
)
func main() {
str := "42 100 -5"
var a, b, c int
n, err := fmt.Sscanf(str, "%d %d %d", &a, &b, &c)
if err != nil {
fmt.Println("Ошибка парсинга:", err)
return
}
fmt.Printf("Прочитано %d чисел: %d, %d, %d\n", n, a, b, c)
}
Плюсы и минусы
- Плюсы: удобно для строк с разделителями (пробелы, запятые); можно парсить сразу несколько чисел.
- Минусы: медленнее, чем
strconv.Atoi(); сложнее обрабатывать ошибки для каждого отдельного числа.
Когда использовать
Если у вас одна строка с одним числом — используйте strconv.Atoi() или ParseInt(). Если строка содержит структурированные данные (например, "25 30 45"), fmt.Sscanf() может быть удобнее.
Также можно комбинировать: сначала разбить строку через strings.Split(), затем каждый элемент преобразовать через strconv.Atoi().
import "strings"
data := "10,20,30"
parts := strings.Split(data, ",")
for _, part := range parts {
num, _ := strconv.Atoi(strings.TrimSpace(part))
fmt.Println(num)
}
Выбирайте подход под вашу конкретную задачу.