Avatar ·

Как преобразовать строку в число (int) в Go?

Всем привет! Я только начал изучать Go и столкнулся с проблемой преобразования строки в целое число. Мне нужно прочитать число из аргумента командной строки или из текстового файла, но в Go строки и числа — это разные типы, и просто так присвоить строку переменной типа int не получается. Например, у меня есть такой код: ```go package main import "fmt" func main() { var s string = "42" var i int = s // Ошибка! fmt.Println(i) } ``` Компилятор выдает ошибку: `cannot use s (type string) as type int in assignment`. Я понимаю, что нужно явное преобразование, но как его сделать правильно? В Python я писал `int("42")`, а в Go `int(s)` не работает. Я пробовал использовать `strconv` пакет, но не совсем понял, как им пользоваться. Подскажите, пожалуйста, как в Go конвертировать строку в число, и как обрабатывать возможные ошибки, если строка не является числом (например, если пользователь ввел "abc" или пустую строку)? Буду благодарен за примеры кода с пояснениями. <<>>

Преобразование строки в int в Go: полное руководство

В Go для преобразования строки в целое число используется пакет strconv (string conversion). Это стандартная библиотека, которая предоставляет несколько функций для разных типов чисел. Рассмотрим основные варианты.

1. Основной способ: strconv.Atoi()

Функция Atoi (ASCII to integer) — самый простой способ для преобразования строки в int. Она возвращает два значения: само число и ошибку (если преобразование невозможно).

package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "42"
    i, err := strconv.Atoi(s)
    if err != nil {
        fmt.Println("Ошибка преобразования:", err)
        return
    }
    fmt.Printf("Число: %d, тип: %T\n", i, i) // Вывод: Число: 42, тип: int
}

2. Работа с разными разрядностями: strconv.ParseInt()

Если вам нужен контроль над разрядностью (например, int32 или int64), используйте ParseInt.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "1234567890"
    // Параметры: строка, система счисления (0 — автоопределение), разрядность (0..64)
    i64, err := strconv.ParseInt(s, 10, 64)
    if err != nil {
        fmt.Println("Ошибка:", err)
        return
    }
    fmt.Printf("int64: %d\n", i64)

    // Для int32
    i32, _ := strconv.ParseInt(s, 10, 32)
    fmt.Printf("int32: %d\n", int32(i32))
}

3. Обработка ошибок: что может пойти не так?

Всегда проверяйте ошибку! Если строка не является числом, содержит лишние символы или выходит за пределы разрядности, strconv вернёт ошибку и нулевое значение.

func safeAtoi(s string) int {
    i, err := strconv.Atoi(s)
    if err != nil {
        // Логируем или возвращаем значение по умолчанию
        fmt.Printf("Не удалось преобразовать '%s': %v\n", s, err)
        return 0
    }
    return i
}

func main() {
    tests := []string{"42", "abc", "", "9999999999999999999"}
    for _, t := range tests {
        result := safeAtoi(t)
        fmt.Printf("'%s' -> %d\n", t, result)
    }
}

4. Преобразование чисел обратно в строку

Для обратной операции используйте strconv.Itoa() (int to ASCII) или strconv.FormatInt():

num := 123
s1 := strconv.Itoa(num)        // "123"
s2 := strconv.FormatInt(int64(num), 10) // "123" (с указанием системы счисления)

5. Рекомендации по использованию

  • Для простых случаев (известно, что строка гарантированно содержит число) — Atoi().
  • Для чисел из внешних источников (пользовательский ввод, файлы, API) — всегда обрабатывайте ошибку.
  • Для больших чисел (более 2^31-1) — используйте ParseInt() с bitSize: 64.
  • Для беззнаковых чисел — strconv.ParseUint().

Вот полный пример для вашей задачи — чтение числа из аргумента командной строки:

package main

import (
    "fmt"
    "os"
    "strconv"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("Использование: program <число>")
        return
    }

    input := os.Args[1]
    number, err := strconv.Atoi(input)
    if err != nil {
        fmt.Printf("Ошибка: '%s' не является целым числом\n", input)
        return
    }

    fmt.Printf("Вы ввели число: %d\n", number)
    // Теперь number — int, можно выполнять арифметические операции
    fmt.Printf("Удвоенное значение: %d\n", number*2)
}

Запомните главное правило: в Go явное преобразование типов — это безопасность. Пакет strconv даёт вам полный контроль над процессом и не даёт "проглотить" некорректные данные.

<<>>

Альтернативный подход: использование fmt.Sscanf

Помимо пакета strconv, в Go есть ещё один способ преобразовать строку в число — функция fmt.Sscanf. Она работает по аналогии с scanf из C и позволяет извлекать данные из строки по шаблону.

package main

import (
    "fmt"
)

func main() {
    s := "42"
    var i int
    _, err := fmt.Sscanf(s, "%d", &i)
    if err != nil {
        fmt.Println("Ошибка:", err)
        return
    }
    fmt.Println("Число:", i) // 42
}

Плюсы этого подхода:

  • Можно извлекать несколько чисел из одной строки, например: fmt.Sscanf("10 20 30", "%d %d %d", &a, &b, &c).
  • Поддерживает разные форматы: шестнадцатеричные (%x), числа с плавающей точкой (%f) и другие.

Минусы:

  • Медленнее, чем strconv.Atoi (из-за парсинга шаблона).
  • Менее гибкая обработка ошибок — Sscanf может вернуть ошибку, если строка содержит лишние символы после числа.

Когда использовать: если вам нужно распарсить строку со сложным форматом (например, "ID: 42, Value: 100") или извлечь несколько значений за один раз. В остальных случаях предпочтительнее strconv.