В Go преобразовать int в string можно с помощью функции strconv.Itoa() из стандартной библиотеки.
Хотя strconv.Itoa — самый прямой и эффективный способ конвертации целочисленного (int) значения в строку (string), в реальных проектах часто встречаются и другие целочисленные типы (int64, uint64) или сценарии, где требуется гибкое форматирование.
Ниже разберём все корректные методы преобразования чисел в строки в Golang, сравним их производительность и выясним, когда какой подход использовать.
Оптимальный
strconv.Itoa эквивалентна FormatInt(int64(i), 10).
num := 42
str := strconv.Itoa(num) // "42"
Хороший №1
fmt.Sprint форматирует операнды, используя форматы по умолчанию, и возвращает полученную строку. Пробелы добавляются между операндами в том случае, если ни один из них не является строкой.
num := 42
str := fmt.Sprint(num) // "42"
Хороший №2
fmt.Sprintf форматирует в соответствии со спецификатором формата и возвращает полученную строку.
num := 42
str := fmt.Sprintf("%d", num) // "42"
Правильный для int64
strconv.FormatInt возвращает строковое представление числа i в заданной системе счисления (где 2 <= основание <= 36). Для представления значений цифр >= 10 используются строчные латинские буквы от ‘a’ до ‘z’.
var num int64 = 42
str := strconv.FormatInt(num, 10) // Base 10: "42"
Правильный для uint64
strconv.FormatUint возвращает строковое представление i в указанной системе счисления, для 2 <= основание <= 36. Для записи цифр со значениями >= 10 используются строчные буквы от ‘a’ до ‘z’.
var num uint64 = 42
str := strconv.FormatUint(num, 10) // "42"
Ошибочный метод
num := 42
str := string(num) // "*", а не "42"
num := 65
str := string(num) // "A", а не "65"
Почему это ошибка?
Код скомпилируется и запустится, но вместо строкового представления числа ("42") вернёт символ с ASCII-кодом 42 (знак звёздочки/умножения '*').
Вместо строкового представления числа ("65") вернёт символ с ASCII-кодом 65 (буква 'A').
Потому что string(num) интерпретирует число как Unicode-код, а не преобразует его в цифры.
Как обнаружить?
Линтер через go vet, предупредят о потенциально неверном использовании string() с числовым аргументом:
$ go vet main.go
main.go:9:9: conversion from int to string yields a string of one rune, not a string of digits
Бенчмарки
package main
import (
"fmt"
"strconv"
"testing"
)
func BenchmarkItoa(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = strconv.Itoa(i)
}
}
func BenchmarkFmtSprint(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = fmt.Sprint(i)
}
}
func BenchmarkFmtSprintf(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = fmt.Sprintf("%d", i)
}
}
func BenchmarkFormatInt(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = strconv.FormatInt(int64(i), 10)
}
}
func BenchmarkFormatUint(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = strconv.FormatUint(uint64(i), 10)
}
}
Запускаем с помощью команды:
go test -v -bench=. -benchmem -benchtime=100000000x .
goos: linux
goarch: amd64
pkg: aaa
cpu: Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz
BenchmarkItoa
BenchmarkItoa-8 100000000 72.87 ns/op 7 B/op 0 allocs/op
BenchmarkFmtSprint
BenchmarkFmtSprint-8 100000000 190.5 ns/op 16 B/op 2 allocs/op
BenchmarkFmtSprintf
BenchmarkFmtSprintf-8 100000000 206.6 ns/op 16 B/op 2 allocs/op
BenchmarkFormatInt
BenchmarkFormatInt-8 100000000 70.23 ns/op 7 B/op 0 allocs/op
BenchmarkFormatUint
BenchmarkFormatUint-8 100000000 67.21 ns/op 7 B/op 0 allocs/op
PASS
ok intbench 60.752s
Если для удобства представить в виде таблицы:
| Метод | Время (ns/op) | Память (B/op) | Аллокации (allocs/op) |
|---|---|---|---|
Itoa | 72.87 | 7 | 0 |
FmtSprint | 190.5 | 16 | 2 |
FmtSprintf | 206.6 | 16 | 2 |
FormatInt | 70.23 | 7 | 0 |
FormatUint | 67.21 | 7 | 0 |
То явно будет видно, что:
- Самые быстрые методы это
strconv.Itoa,strconv.FormatIntиstrconv.FormatUintу которых разница в переделах 8% fmt.Sprintиfmt.Sprintfпредоставляют больше удобства и гибкости в форматировании, но сильно прогирывают как по чистой скорости исполнения, так и по наличию аллокаций в куче
Финальные рекомендации
- По возможности используйте FormatInt/FormatUint
stroconv.Itoaдаёт отличный баланс эргономики разработки и производительности- Избегайте fmt-методов без явной на то необходимости
FAQ
Как преобразовать int в строку в Golang?
Используйтеstrconv.Itoa() или fmt.Sprintf(). Конкретные примеры можно посмотреть выше.Как конвертировать int32 в строку в Golang?
Для правильной конвертации потребуется сначала привестиint32 к int64 типу и только после проводить конвертацию.
Например вот так: strconv.FormatInt(int64(var), 10).Как конвертировать int64 в строку в Golang?
Используйтеstrconv.FormatInt(var, 10), так как Itoa работает только с int.Почему при конвертации int в строку получается один символ (rune)?
Вы, вероятно, используетеstring(i) напрямую. Это интерпретирует число как Unicode-код. Используйте strconv или fmt.Как конвертировать uint64 в строку в Golang?
Похожим образом как и дляint32 сначала привести uint32 к uint64 и только после проводить конвертацию.
strconv.FormatUint(uint64(var), 10).Теги: