GoGo example

How to convert an int to a string in Go

6 min read▶ Runs in an isolated hosted runtimeUpdated Aug 2026

Quick answer

Use strconv.Itoa: s := strconv.Itoa(42) gives "42". Do not write string(42) — that's a code-point conversion and returns "*", not "42".

This is the conversion Go makes people trip over exactly once. The obvious spelling, string(n), compiles happily and does something completely different: it treats the integer as a Unicode code point, so string(65) is "A". The real answer lives in strconv, where Itoa handles the everyday case and FormatInt covers bases and widths — and unlike the reverse direction, none of it can fail, so there is no error to check. Each example runs on this page — hit Run, then edit and run it again.

1strconv.ItoaRecommended

strconv.Itoa(n) ("integer to ASCII", C heritage again) takes an int and returns its base-10 decimal text. One argument, one return value, no error — an integer always has a decimal spelling, so there is nothing to go wrong. This is the call to reach for unless you specifically need another base or a formatted layout.

itoa.go

Output

Prints 42!, then 2 (the string is two characters long), -17, and 43. The concatenation on the first line is the proof: n + "!" would not compile, because Go never converts between int and string implicitly. Itoa is a thin wrapper over FormatInt(int64(n), 10) with a fast path for small values.

2FormatInt: any base, and int64

strconv.FormatInt(n, base) is the general form. base is anything from 2 to 36 — digits then lowercase letters — and the argument is an int64, so it is also the answer to "how do I convert an int64 to a string". Its unsigned twin FormatUint takes a uint64 and reaches values an int64 cannot hold at all.

formatint.go

Output

Prints 255, 11111111, ff, 73, then -ff, 18446744073709551615 and 42. Note the hex comes out lowercase and unprefixed — no 0x. If you want the prefix or uppercase digits, that is a formatting decision, and fmt.Sprintf("%#X", n) is the shorter road to it.

3fmt.Sprintf when you need formatting

fmt.Sprintf("%d", n) also produces "42", and for a bare conversion it is the slower, wordier choice — it goes through reflection to work out the type. But the moment you want padding, a forced sign, a different base, or other text around the number, it stops being a conversion and starts being formatting, and that is exactly Sprintf's job.

sprintf.go

Output

Prints 42, then 00042 +42, then 11111111 377 ff FF, then order #1042: 3 items, 15% off, then 42 {1 2}. Two things worth stealing: %05d is how you get leading zeros (order numbers, invoice IDs), and a literal percent sign is %%. fmt.Sprint(n) with no verb works too and is handy in generic code, but for a plain int prefer Itoa.

4The string(i) trap

string(n) is legal Go and it is almost never what you want. Go's conversion syntax reinterprets a value; it does not parse or format one. Converting an integer to a string means "the character at this code point", so string(65) is "A" and small numbers land on invisible control characters. go vet catches it: conversion from int to string yields a string of one rune, not a string of digits.

trap.go

Output

Prints "A" where you expected "65", then "65" from Itoa, then , then Go twice, and finally "\a" vs "7" — code point 7 is the BEL control character, which would have vanished silently in normal output. string() of a []byte or []rune is genuinely useful and not a trap; only the single-integer form is. Run go vet ./... in CI and this class of bug never reaches you.

5Which should you use?

MethodReturnsHandlesBest for
strconv.ItoastringBase-10 intAlmost everything
strconv.FormatIntstringBases 2–36, int64Hex/binary, int64 values
strconv.FormatUintstringuint64, unsigned onlyIDs, sizes, bitmasks
fmt.Sprintf("%d")stringPadding, signs, textMessages and layout
strconv.AppendInt[]byteWrites into your bufferHot loops, zero extra allocs
string(i)string — one rune!Code points, not digitsNever, for numbers

6Building a string from many ints

There is no strings.Join for []int, so joining numbers means converting first. Strings are immutable, so out += strconv.Itoa(n) in a loop copies the whole accumulated string every iteration — O(n²) work and O(n) garbage. strings.Builder keeps one growing buffer, and strconv.AppendInt goes one step further by writing the digits directly into a []byte you own, with no intermediate string at all.

many.go

Output

Prints 1, 1, 2, 3, 5, 8, 13, then 1-1-2-3-5-8-13, then 1 1 2 3 5 8 13, then 11235813 — same digits, four different costs. For a handful of values any of them is fine and the Itoa-then-Join version reads best; inside a hot loop or a serializer, AppendInt into a reused buffer is the one that stops showing up in your allocation profile.

Frequently asked questions

Why does string(65) give "A" instead of "65" in Go?

Because string(x) on an integer is a type conversion, not formatting — it means "the character at this Unicode code point", and code point 65 is the letter A. Use strconv.Itoa(65) to get the digits "65". go vet flags the integer form with "conversion from int to string yields a string of one rune, not a string of digits", so running vet in CI catches it for you.

What is the difference between strconv.Itoa and fmt.Sprintf("%d")?

They produce the same string, but Itoa is a direct base-10 formatter while Sprintf goes through the reflection-based fmt machinery to discover the argument type, which makes it measurably slower and allocates more. Use Itoa for a plain conversion and Sprintf when you actually need formatting — padding like %05d, a forced sign with %+d, or the number embedded in other text.

How do I convert an int64 to a string in Go?

Call strconv.FormatInt(n, 10) — it takes an int64 directly. strconv.Itoa(int(n)) also works on 64-bit platforms where int is 64 bits wide, but it silently truncates on a 32-bit build, so FormatInt is the correct call whenever the value is genuinely 64-bit. For unsigned values use strconv.FormatUint(u, 10).

How do I convert an int to a string with leading zeros?

Use fmt.Sprintf("%05d", n), which pads with zeros to a width of 5 — 42 becomes "00042". strconv has no padding option at all, so this is one of the cases where Sprintf is the right tool rather than the lazy one. Use %5d for space padding and %-5d to left-align.

How do I join a slice of ints into a comma-separated string?

strings.Join only takes a []string, so convert first: build a []string with strconv.Itoa in a loop and then strings.Join(parts, ", "). For large slices or hot paths, write into a strings.Builder instead, or use strconv.AppendInt to append the digits straight into a reused []byte and skip the intermediate strings entirely.

How do I convert a float or a bool to a string in Go?

The same package covers them: strconv.FormatFloat(3.14159, 'f', 2, 64) gives "3.14" (format byte, precision, bit size) and strconv.FormatBool(true) gives "true". fmt.Sprintf("%.2f", f) is the formatting-oriented equivalent for floats. And strconv.Quote(s) wraps a string in Go-syntax quotes, which is what %q prints.