The strconv package converts between strings and the basic Go types — int, float64, bool. Anything that comes in as text (from a user, a file, a network request) and needs to become a number, or vice versa, goes through strconv.

Import it:

import "strconv"

At a glance

DirectionSimplePowerful
string → intAtoiParseInt
int → stringItoaFormatInt
string → floatParseFloat
float → stringFormatFloat
string → boolParseBool
bool → stringFormatBool
Add escapes/quotesQuote, Unquote

Use the simple version when you have a base-10 integer string. Use the powerful version when you need to control base (binary, hex), bit size, or precision.

The rest of this page walks through each pair with examples.

Integers

Atoi and Itoa — the everyday pair

The names come from C: ASCII to integer and the reverse.

n, err := strconv.Atoi("42")           // n = 42, err = nil
if err != nil {
    // handle bad input
}

s := strconv.Itoa(42)                  // s = "42"

Atoi only handles base-10 integers that fit in an int. For anything fancier, use ParseInt.

ParseInt — base and bit size

strconv.ParseInt(s, base, bitSize)
  • base: 0 (auto-detect from 0x/0o/0b prefix), or 236
  • bitSize: 0 (int), 8, 16, 32, 64. Limits the value range.
strconv.ParseInt("42", 10, 64)         // 42, nil
strconv.ParseInt("ff", 16, 64)         // 255, nil
strconv.ParseInt("1010", 2, 64)        // 10, nil
strconv.ParseInt("0xff", 0, 64)        // 255, nil  (auto-detect from prefix)

strconv.ParseInt("300", 10, 8)         // 0, error (300 > int8 max of 127)

The return type is always int64 regardless of bitSize — you cast it down yourself:

n64, _ := strconv.ParseInt("100", 10, 32)
n := int32(n64)

FormatInt — int to string in any base

strconv.FormatInt(42, 10)              // "42"
strconv.FormatInt(255, 16)             // "ff"
strconv.FormatInt(10, 2)               // "1010"
strconv.FormatInt(-42, 10)             // "-42"

FormatInt takes an int64, so cast up if you have a smaller int:

n := int32(42)
s := strconv.FormatInt(int64(n), 10)   // "42"

Itoa(n) is just FormatInt(int64(n), 10). Use Itoa when you have an int and want base 10. Use FormatInt for everything else.

Unsigned variants — ParseUint and FormatUint

Same shape as ParseInt/FormatInt, but for uint64. Use these when negative values would be a bug (port numbers, sizes, IDs).

strconv.ParseUint("8080", 10, 16)      // 8080, nil
strconv.FormatUint(8080, 10)           // "8080"

Floats

ParseFloat

strconv.ParseFloat("3.14", 64)         // 3.14, nil
strconv.ParseFloat("1e6", 64)          // 1000000, nil
strconv.ParseFloat("not a number", 64) // 0, error

The second arg is the bit size: 32 or 64. Use 64 unless you have a reason not to.

FormatFloat

strconv.FormatFloat(f, format, precision, bitSize)

The format byte chooses the output style:

FormatWhat it doesExample for 3.14159
'f'Plain decimal"3.14159"
'e'Scientific (lowercase e)"3.14159e+00"
'E'Scientific (uppercase E)"3.14159E+00"
'g'%e for large/small, %f otherwise"3.14159"
'b'Binary exponent form (rare)
strconv.FormatFloat(3.14159, 'f', 2, 64)    // "3.14"
strconv.FormatFloat(3.14159, 'f', -1, 64)   // "3.14159"  (-1 = shortest accurate)
strconv.FormatFloat(1234.5, 'e', 3, 64)     // "1.234e+03"

For most uses, fmt.Sprintf("%.2f", x) is cleaner than FormatFloat. Reach for FormatFloat when you need the exact shortest representation (precision = -1).

Booleans

strconv.ParseBool("true")              // true, nil
strconv.ParseBool("1")                 // true, nil
strconv.ParseBool("yes")               // false, error  (only 1/t/T/TRUE/true/True and 0/f/F/FALSE/false/False)

strconv.FormatBool(true)               // "true"

ParseBool accepts a fixed set of strings. For anything else (like "yes"/"no"), match it yourself.

Quoting strings

Quote and Unquote handle Go-style string literals — adding escape sequences, surrounding quotes, etc. Useful when generating Go code, logging values safely, or parsing config files that use Go-quoted strings.

strconv.Quote("Hello\nWorld")          // `"Hello\nWorld"`  (with literal \n)
strconv.Quote(`raw "quoted" text`)     // `"raw \"quoted\" text"`

s, err := strconv.Unquote(`"Hello\nWorld"`)
// s = "Hello\nWorld"  (the actual newline character)

Variants:

  • QuoteRune('A')"'A'"
  • QuoteToASCII("héllo")"\"h\\u00e9llo\"" (escapes non-ASCII)
  • Unquote works on "...", '...', and `...`.

Handling errors — NumError

Every Parse* function returns an error that’s actually a *strconv.NumError. You can extract it with errors.As to see exactly what went wrong:

n, err := strconv.Atoi("abc")
if err != nil {
    var numErr *strconv.NumError
    if errors.As(err, &numErr) {
        fmt.Println("Function:", numErr.Func)  // "Atoi"
        fmt.Println("Input:", numErr.Num)      // "abc"
        fmt.Println("Inner:", numErr.Err)      // strconv.ErrSyntax
    }
}

Two sentinel errors you can check against:

  • strconv.ErrSyntax — the string wasn’t a valid number
  • strconv.ErrRange — the number was valid but didn’t fit in the bit size
_, err := strconv.ParseInt("999999999999999999999", 10, 32)
errors.Is(err, strconv.ErrRange)       // true

Common interview patterns

Read an int from stdin

var s string
fmt.Scan(&s)
n, err := strconv.Atoi(s)
if err != nil {
    fmt.Println("not a valid number")
    return
}
fmt.Println("doubled:", n*2)

Parse a hex color string

hex := "ff8800"
n, _ := strconv.ParseUint(hex, 16, 32)
r := (n >> 16) & 0xff   // 255
g := (n >> 8) & 0xff    // 136
b := n & 0xff           // 0

Convert a slice of ints to a comma-separated string

nums := []int{1, 2, 3, 4}
parts := make([]string, len(nums))
for i, n := range nums {
    parts[i] = strconv.Itoa(n)
}
result := strings.Join(parts, ",")     // "1,2,3,4"

Sum the digits of a number-string

func digitSum(s string) (int, error) {
    sum := 0
    for _, c := range s {
        d, err := strconv.Atoi(string(c))
        if err != nil {
            return 0, err
        }
        sum += d
    }
    return sum, nil
}

Quick rules of thumb

  • Base-10 int from a string?Atoi
  • Int to base-10 string?Itoa
  • Any other base, or need bit-size control?ParseInt / FormatInt
  • Floats?ParseFloat(s, 64); for printing use fmt.Sprintf("%.2f", x)
  • Bool from text?ParseBool (handles true/false/1/0/t/f etc.)
  • Need to know why parsing failed?errors.Is(err, strconv.ErrSyntax) or ErrRange

Common mistakes

  • Ignoring the error from Atoin, _ := strconv.Atoi(s) silently gives 0 on bad input, which is a bug waiting to happen.
  • Using Atoi for hexAtoi("ff") fails. Use ParseInt("ff", 16, 64).
  • Forgetting to cast ParseInt’s int64 resultvar n int = strconv.ParseInt(...) won’t compile.
  • fmt.Sprintf("%d", n) vs strconv.Itoa(n) — both work; Itoa is faster and clearer when you only need the number.
  • ParseBool("yes") — fails. The valid strings are 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
Toggle theme (T)