Menu

Golang Int to String, String to Int, and Type Conversion

How to convert between types in Go: int to string and string to int with strconv, floats to ints, numeric conversions with T(v), bytes and runes, the string(65) trap, and handling conversion errors.

This page includes runnable editors - edit, run, and see output instantly.

Go never converts types implicitly. You convert between compatible types with T(v), and between numbers and text with the strconv package. The two most searched conversions:

strconv.Itoa ("integer to ASCII") formats an int as decimal text. strconv.Atoi ("ASCII to integer") parses text into an int and returns an error when the text is not a valid number. Always check that error.

The T(v) Conversion

Go's conversion syntax looks like a function call named after the target type. It works in three situations:

  1. between numeric types (int, int64, float64, uint8, ...),
  2. between string and []byte or []rune,
  3. between types that share an underlying type (Celsius and float64).

Read the results closely:

  • int(3.9) is 3 and int(-3.9) is -3. Conversion truncates toward zero; it does not round. Use math.Round, math.Floor or math.Ceil first to choose the behavior. math.Round rounds half away from zero, so -3.5 becomes -4.
  • uint8(300) is 44, because only the low 8 bits survive (300 minus 256), and int8(200) is -56 for the same reason. No error, no panic.
  • Celsius and float64 share an underlying type, so they convert freely, but only explicitly.

The values are in variables on purpose. With constants, the same conversions do not compile.

Constants Are Checked, Variables Are Not

Converting a constant that does not fit is a compile error. Converting a variable with the same value silently wraps:

fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8

Converting a non-integer constant to an integer type is also rejected, while the same value in a variable is truncated:

./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int

If the float value is outside the range of the target integer type (say int64(1e20)), the result is implementation-dependent: amd64 and arm64, for example, give different answers. Check the range before converting untrusted values.

Converting Numbers to Strings

FromFunctionExampleResult
intstrconv.Itoa(n)strconv.Itoa(-7)"-7"
int64strconv.FormatInt(n, base)strconv.FormatInt(255, 16)"ff"
uint64strconv.FormatUint(n, base)strconv.FormatUint(5, 2)"101"
float64strconv.FormatFloat(f, fmt, prec, 64)strconv.FormatFloat(3.14159, 'f', 2, 64)"3.14"
boolstrconv.FormatBool(b)strconv.FormatBool(true)"true"
anythingfmt.Sprint(v)fmt.Sprint(3.5)"3.5"
anything, formattedfmt.Sprintf(format, v)fmt.Sprintf("%05d", 42)"00042"

FormatFloat takes a format byte ('f' for fixed, 'e' for exponent, 'g' for whichever is shorter), a precision (-1 means "the fewest digits that round-trip exactly"), and the bit size of the original float (64 or 32).

strconv is faster than fmt.Sprint, which boxes the value in an interface and goes through fmt's general formatting path. In a hot loop that difference shows up; for occasional conversions, pick whichever reads better.

Converting Strings to Numbers

ToFunctionReturns
intstrconv.Atoi(s)int, error
any signed intstrconv.ParseInt(s, base, bitSize)int64, error
any unsigned intstrconv.ParseUint(s, base, bitSize)uint64, error
floatstrconv.ParseFloat(s, bitSize)float64, error
boolstrconv.ParseBool(s)bool, error

ParseInt always returns an int64. The bitSize argument (0, 8, 16, 32, 64) sets the range it accepts, so the result is guaranteed to fit when you convert it down. base 0 means "infer from the prefix", so 0x1f, 0o17, 0b101 and 1_000 all parse.

Things the output shows:

  • " 42" fails. Atoi accepts an optional sign and digits, nothing else. Input from bufio usually ends in \n, so trim it.
  • "4.2" is invalid for Atoi. Use ParseFloat for decimals.
  • On an out-of-range error, ParseInt returns the largest value that fits (127 for int8) together with the error. Do not use the value when the error is not nil.
  • The errors are *strconv.NumError values wrapping strconv.ErrSyntax or strconv.ErrRange, so errors.Is can tell them apart.

ParseBool accepts 1, t, T, TRUE, true, True and the matching false forms. "yes" and "on" are errors.

The string(65) Trap

Converting an integer to string does not produce digits. It produces the character with that Unicode code point:

n := 65
s := string(n) // "A", not "65"

The compiler accepts it, but go vet reports it:

./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits

If you really want the character, say so with a rune: string(rune(n)). If you want the number as text, use strconv.Itoa(n). Converting a rune or byte to string is fine and common:

Strings, Bytes and Runes

string, []byte and []rune convert into each other with T(v). Each conversion copies the data, because strings are immutable and slices are not:

Convert to []rune when you need to index or modify by character; convert to []byte for I/O, hashing and byte-level edits. Runes and bytes covers UTF-8 in detail.

Conversion vs Type Assertion

A conversion changes a value from one concrete type to another. Getting the concrete value out of an interface (any, error, io.Reader) is a different operation, the type assertion:

var v any = 42

n := v.(int)       // type assertion: v holds an int, give it to me
f := float64(n)    // conversion: int to float64
// f := float64(v) // compile error: cannot convert v (variable of interface type any)
//                  // to type float64: need type assertion

Assert first, then convert. The comma-ok form n, ok := v.(int) avoids a panic when the type is wrong.

Quick Reference

TaskCode
int to stringstrconv.Itoa(n)
int64 to stringstrconv.FormatInt(n, 10)
string to intn, err := strconv.Atoi(s)
string to int64n, err := strconv.ParseInt(s, 10, 64)
string to float64f, err := strconv.ParseFloat(s, 64)
float64 to stringstrconv.FormatFloat(f, 'f', -1, 64)
float64 to intint(f) (truncates) or int(math.Round(f))
int to float64float64(n)
string to []byte[]byte(s)
[]byte to stringstring(b)
rune to stringstring(r)
bool to stringstrconv.FormatBool(b)
any value to stringfmt.Sprint(v)

Frequently Asked Questions

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

Use strconv.Itoa(n): strconv.Itoa(42) returns "42". For an int64 use strconv.FormatInt(n, 10). fmt.Sprint(n) also works for any type but is slower. Do not write string(n): that treats n as a Unicode code point, so string(65) is "A".

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

Use strconv.Atoi, which returns the number and an error:

n, err := strconv.Atoi("42")
if err != nil {
	// not a valid integer
}

For a specific size or base, use strconv.ParseInt(s, 10, 64), which returns an int64. Atoi does not trim spaces, so " 42" is an error; call strings.TrimSpace first.

How do I cast in Go?

Go calls it conversion, and the syntax is T(v): float64(n), int(f), []byte(s). It works between numeric types, between strings and byte or rune slices, and between types with the same underlying type. It does not parse text: turning "42" into 42 needs strconv. Getting a concrete type out of an interface is a type assertion, v.(T), not a conversion.

How do I convert a float to an int in Go?

int(f) truncates toward zero: int(3.9) is 3 and int(-3.9) is -3. To round, use int(math.Round(f)). If the float is outside the range of the integer type the result is implementation-specific, so check the range first when the value comes from input.

Why does string(65) return "A" in Go?

Converting an integer to string interprets it as a Unicode code point, and 65 is the code point of A. go vet flags it: conversion from int to string yields a string of one rune, not a string of digits. Use strconv.Itoa(65) to get "65".

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED