Все способы конвертации int в string
Оптимальный
num := 42
str := strconv.Itoa(num) // "42"
Хороший №1
num := 42
str := fmt.Sprint(num) // "42"
Хороший №2
num := 42
str := fmt.Sprintf("%d", num) // "42"
Правильный для int64
var num int64 = 42
str := strconv.FormatInt(num, 10) // Base 10: "42"
Правильный для uint64
var num uint64 = 42
str := strconv.FormatUint(num, 10) // "42"
Ошибочный метод
num := 65
str := string(num) // "A" (символ ASCII), а не "65"
Почему это ошибка?
Код скомпилируется и запустится, но вместо строкового представления числа ("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-методов без явной на то необходимости