Avatar ·

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

Всем привет! Я только начал изучать Go и столкнулся с, казалось бы, простой задачей: нужно вывести на экран сообщение, которое содержит число и текст. Например, я хочу получить строку "Результат: 42", где 42 — это переменная типа int. В Python я бы просто написал `"Результат: " + str(42)`, и всё бы заработало. В Go я попробовал сделать так: ```go package main import "fmt" func main() { score := 42 message := "Результат: " + score fmt.Println(message) } ``` Но компилятор выдаёт ошибку: `cannot use score (variable of type int) as type string in concatenation`. Я понимаю, что Go — строго типизированный язык, но как же мне преобразовать int в строку? Я перепробовал несколько вариантов: 1. Пытался использовать `string(score)`, но получил в выводе символ "*" (звёздочку) вместо числа 42. 2. Пытался использовать fmt.Sprintf, но не уверен, что это правильный способ. Подскажите, пожалуйста, какой самый правильный и идиоматичный способ в Go для конвертации int в string? Есть ли несколько вариантов, и какой из них лучше использовать в разных ситуациях? Заранее спасибо! <<>>

Основные способы преобразования int в string в Go

Вы абсолютно правы: Go — строго типизированный язык, и простое сложение строки и числа не сработает. Главная причина, почему string(score) даёт звёздочку, а не число, заключается в том, что string() в Go интерпретирует целое число как код символа Unicode (rune). Число 42 — это код символа '*', поэтому вы его и видите. Это не преобразование числа в его текстовое представление, а приведение к символу.

Рассмотрим три основных корректных подхода, начиная с самого популярного.

1. Пакет strconv — самый правильный способ

Стандартный пакет strconv содержит функцию Itoa() (Integer to ASCII):

package main

import (
    "fmt"
    "strconv"
)

func main() {
    score := 42
    message := "Результат: " + strconv.Itoa(score)
    fmt.Println(message) // Вывод: Результат: 42
}

Это самый идиоматичный и производительный способ для базового преобразования int в string. Функция Itoa() работает быстрее, чем fmt.Sprintf, потому что не занимается форматированием строк.

Если вам нужно преобразовать число в строку с определённой системой счисления (например, в двоичную или шестнадцатеричную), используйте strconv.FormatInt():

package main

import (
    "fmt"
    "strconv"
)

func main() {
    score := 42
    
    // Десятичная система (основание 10) — аналог Itoa
    decStr := strconv.FormatInt(int64(score), 10)
    fmt.Println(decStr) // "42"
    
    // Двоичная система
    binStr := strconv.FormatInt(int64(score), 2)
    fmt.Println(binStr) // "101010"
    
    // Шестнадцатеричная система
    hexStr := strconv.FormatInt(int64(score), 16)
    fmt.Println(hexStr) // "2a"
}

2. fmt.Sprintf — для сложного форматирования

Если вам нужно встроить число в строку с дополнительным форматированием (выравнивание, количество знаков), используйте fmt.Sprintf:

package main

import "fmt"

func main() {
    score := 42
    name := "Игрок"
    
    // Простое встраивание
    message := fmt.Sprintf("Результат %s: %d", name, score)
    fmt.Println(message) // "Результат Игрок: 42"
    
    // С выравниванием (ширина поля 10 символов)
    aligned := fmt.Sprintf("Счёт: |%10d|", score)
    fmt.Println(aligned) // "Счёт: |        42|"
}

Важно: fmt.Sprintf медленнее strconv.Itoa из-за внутреннего разбора строки формата. Используйте его только когда нужно форматирование, а не просто преобразование.

3. Пакет strconv.FormatInt — для особых случаев

Как показано выше, этот метод нужен, когда вы работаете с int64 (или другим конкретным размером int) или хотите указать систему счисления. Для обычного int всегда предпочитайте strconv.Itoa().

Рекомендации

  • Для простой конвертации int → string: используйте strconv.Itoa().
  • Для встраивания в строку с другими данными: используйте fmt.Sprintf.
  • Для работы с разными системами счисления: используйте strconv.FormatInt().
  • Никогда не используйте string(intValue) — это приведёт к неожиданным результатам (как в вашем примере со звёздочкой).

Надеюсь, теперь всё стало понятно! Go требует явного преобразования, но это делает код более предсказуемым и безопасным.

<<>>

Альтернативный способ: пакет fmt с функцией Sprint

Если вы не хотите использовать strconv или Sprintf, можно воспользоваться функцией fmt.Sprint(). Она принимает любые аргументы и возвращает их строковое представление, соединённое без пробелов:

package main

import "fmt"

func main() {
    score := 42
    message := "Результат: " + fmt.Sprint(score)
    fmt.Println(message) // Вывод: Результат: 42
}

Этот способ удобен, когда у вас уже импортирован пакет fmt (например, для вывода в консоль), и вы не хотите добавлять ещё один импорт strconv. Однако помните, что fmt.Sprint работает медленнее, чем strconv.Itoa, из-за рефлексии — Go должен определить тип аргумента во время выполнения.

Когда использовать

  • В небольших скриптах или прототипах, где производительность не критична.
  • Когда вы уже используете fmt и хотите избежать лишнего импорта.
  • Для быстрого преобразования нескольких значений разного типа в одну строку (fmt.Sprint(42, "hello", 3.14)).

Но для production-кода лучше всё же использовать strconv.Itoa() — это быстрее, явнее и соответствует идиомам Go.

Ещё один совет: если вам нужно преобразовать int64 или uint64, не забывайте, что strconv.Itoa() работает только с int. Для других целочисленных типов используйте strconv.FormatInt() или strconv.FormatUint().