strconv in Go: parse, format, quote, and common errors

strconv in Go: parse and format integers, floats, and bools, Quote and Unquote, bases with FormatUint and ParseInt, NumError with errors.Is, and when to prefer strconv over fmt.Sscanf.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

strconv in Go: parse, format, quote, and common errors

The strconv package is the standard library’s dedicated string ↔ scalar toolkit: parse user input and configuration into numbers and booleans, format values for display and logs, and emit Go string literals with Quote / Unquote. It is small, fast, and returns an error on invalid input—unlike many fmt helpers that are optimized for printing, not strict validation.

I ran the examples in this guide on Go 1.22+ (Linux) with go run and small tests so I could confirm ParseBool, Atoi with surrounding spaces, and FormatUint in several bases match what you see in the listings.


What Is strconv in Go?

strconv lives in the standard library and focuses on parsing (ParseInt, Atoi, ParseFloat, ParseBool, …) and formatting (FormatInt, Itoa, FormatFloat, FormatBool, …), plus quoted literals (Quote, Unquote, …). For the full surface (including AppendInt and friends), keep the package docs open while you work.

When to use strconv instead of fmt

  • Prefer strconv when you need a typed result and a clear error for bad input—for example CLI flags, HTTP query parameters, environment variables, and protocol fields.
  • fmt.Sscanf and fmt.Fscanf can work for ad-hoc parsing, but format strings are easy to get wrong, errors are harder to classify, and they are usually not the first choice for production validation.

For general printing without strict parsing rules, fmt.Printf and related printers remain the right tool.


Quick strconv Reference Table

Common string conversion functions

Task Function Example use case
String → int strconv.Atoi Simple decimal text such as "42"
int → string strconv.Itoa Decimal text for UI or concatenation
String → signed integer strconv.ParseInt Other bases, explicit int64/int32 width, strict flags
String → unsigned integer strconv.ParseUint Ports, bitmasks, IDs parsed as unsigned
String → bool strconv.ParseBool Environment variables and JSON-like "true" / "false"
float64 → string strconv.FormatFloat Human-readable decimals with precision control
uint64 → string (radix) strconv.FormatUint Decimal, binary, octal, hex output
String for logs / literals strconv.Quote Safe, escaped representation of arbitrary text
Parse a quoted literal strconv.Unquote Interpret a double-quoted Go string literal in text

Convert Strings to Numbers in Go

Convert string to int using strconv.Atoi

Atoi parses a base-10 string into an int. The documentation states it is equivalent to ParseInt(s, 10, 0) converted to int. Leading signs are allowed; leading or trailing spaces are not.

go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	n, err := strconv.Atoi("12345")
	if err != nil {
		panic(err)
	}
	fmt.Println(n) // 12345
}

Convert string to int64 using strconv.ParseInt

ParseInt parses base 2–36 (use 0 to accept 0x / 0o / 0b prefixes per Go rules) and enforces a bit size of 0, 8, 16, 32, or 64. Bit size 0 means an int or int64 sized to the literal.

go
v, err := strconv.ParseInt("ff", 16, 64) // 255
if err != nil {
	panic(err)
}

Convert string to uint64 using strconv.ParseUint

ParseUint is the unsigned counterpart—useful for ports, modes, and IDs that should not be negative.

go
port, err := strconv.ParseUint("8080", 10, 16)
if err != nil {
	panic(err)
}
// port is uint64; cast to uint16 for net.Dial if needed

Convert string to float using strconv.ParseFloat

ParseFloat parses decimal and exponent forms into float32 or float64 depending on the bitSize argument (32 or 64).

go
f, err := strconv.ParseFloat("3.14159", 64)
if err != nil {
	panic(err)
}

Convert Numbers to Strings in Go

Convert int to string using strconv.Itoa

Itoa formats an int in base 10. The docs state it is equivalent to FormatInt(int64(i), 10).

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

Convert int64 using strconv.FormatInt

FormatInt formats a signed integer in bases 2–36 (digits beyond 9 use az).

go
strconv.FormatInt(-255, 16) // "-ff"

Convert uint64 using strconv.FormatUint

FormatUint returns the string form of a uint64 in the given base (2–36); bases above 10 use lowercase letters for digit values ≥ 10, as documented on the function.

go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	u := uint64(255)
	fmt.Println("base10:", strconv.FormatUint(u, 10)) // 255
	fmt.Println("base2: ", strconv.FormatUint(u, 2))  // 11111111
	fmt.Println("base8: ", strconv.FormatUint(u, 8))  // 377
	fmt.Println("base16:", strconv.FormatUint(u, 16)) // ff
}

Typical uses: decimal IDs, binary bit patterns, octal file modes (0755 style without the leading 0 is still often built with formatting helpers), and hex dumps.

Convert float using strconv.FormatFloat

FormatFloat takes the fmt byte ('f', 'e', 'g', …), precision, and bitSize (32 or 64).

go
strconv.FormatFloat(3.14159, 'f', 2, 64) // "3.14"

Convert Strings to Boolean Values

Use strconv.ParseBool

ParseBool returns the bool represented by the string. The documentation lists accepted values: 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False. Any other value returns an error.

Accepted true and false values

Input Result
"true" true, nil error
"TRUE" true, nil error
"1" true, nil error
"t" true, nil error
"false" false, nil error
"FALSE" false, nil error
"0" false, nil error
"f" false, nil error
"yes" error (invalid syntax)
"no" error (invalid syntax)

Many newcomers expect "yes" / "no" to work; they do not. Normalize such strings yourself (for example with a switch) or accept only the documented spellings.

go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	for _, s := range []string{"true", "0", "yes"} {
		b, err := strconv.ParseBool(s)
		fmt.Printf("%q -> %v err=%v\n", s, b, err)
	}
}

Quote and Unquote Strings in Go

Quote returns a double-quoted Go string literal representing s, using Go escapes such as \t, \n, \xFF, and \u0100 for control and non-printable characters, as described in the docs. That makes it ideal when you want log lines or debug output that stay readable and unambiguous.

Escape strings using strconv.Quote

Typical tasks:

  • Logs and errors — show control characters without breaking log line structure.
  • Generated Go code — emit string fields that compile as literals.
  • Debugging — reveal invisible characters (spaces, BOM, odd Unicode) via escapes.
go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	fmt.Println(strconv.Quote("line1\nline2\tend"))
}

QuoteToASCII forces non-ASCII runes into \u / \U escapes so the whole literal is ASCII-only—handy for ASCII-only transports.

Convert quoted strings back using strconv.Unquote

Unquote interprets a double-quoted Go string literal (including escapes) and returns the decoded string. The argument must include the surrounding quotes.

go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	s, err := strconv.Unquote(`"hello\tworld"`)
	if err != nil {
		panic(err)
	}
	fmt.Println(s) // hello + tab + world
}

For single-quoted rune literals, see QuoteRune and UnquoteChar.


Common strconv Errors and Fixes

Parse functions return errors that unwrap to strconv.ErrSyntax or strconv.ErrRange inside a *strconv.NumError. Use errors.Is instead of == on the sentinels alone.

Handle invalid syntax errors

go
package main

import (
	"errors"
	"strconv"
)

func main() {
	if _, err := strconv.Atoi("12x"); errors.Is(err, strconv.ErrSyntax) {
		// not a valid integer literal for the chosen parser
	}
}

Handle value out of range errors

go
package main

import (
	"errors"
	"strconv"
)

func main() {
	if _, err := strconv.ParseInt("9999999999999999999999999999999", 10, 64); errors.Is(err, strconv.ErrRange) {
		// does not fit int64 (for ParseInt with bitSize 64)
	}
}

Trim spaces before conversion

Atoi and friends do not trim spaces. " 42 " fails with a syntax error; use strings.TrimSpace (or a more specific normalizer) first.

go
package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	n, err := strconv.Atoi(strings.TrimSpace("  42 "))
	fmt.Println(n, err)
}

strconv Cheat Sheet

Atoi vs ParseInt vs Itoa vs FormatInt

Function Best for Returns
Atoi Quick base-10 string → int int, error
ParseInt Custom base, explicit bit size int64, error
Itoa Quick int → base-10 string string
FormatInt Signed integers in any allowed base string

Unsigned mirrors: ParseUint / FormatUint.

Append helpers (no separate chapter)

AppendBool, AppendInt, AppendFloat, AppendQuote, and related functions append UTF-8 bytes into an existing []byte buffer—useful to avoid extra allocations when building messages or wire formats. They are intentionally thin wrappers; see the package index for signatures.


Common strconv Use Cases

Read numbers from command-line arguments

After flag parsing—or when reading os.Args[1:]—pass the string slice values through Atoi / ParseInt / ParseUint and check errors before using the numbers.

Parse environment variables into bool and int values

os.LookupEnv returns a string; trim and validate before ParseBool or Atoi. Remember ParseBool only accepts the documented tokens—map yes / no yourself if required.

Convert database IDs from string to uint64

External systems often expose numeric IDs as decimal strings. ParseUint(s, 10, 64) keeps the full unsigned range; downcast only when you know the value fits a smaller type.

Format integers as binary, octal, and hexadecimal

Use FormatUint (or FormatInt for signed values) with bases 2, 8, and 16 for diagnostics, permissions-style octal, and hex dumps.

Quote strings safely for logs and debugging

Wrap arbitrary user or wire content with Quote (or QuoteToASCII) so newlines, tabs, and binary bytes cannot corrupt log parsers or hide data.


References


Frequently Asked Questions

1. Why does err == strconv.ErrSyntax fail after ParseInt?

Parse functions return *strconv.NumError that wraps ErrSyntax or ErrRange. Use errors.Is(err, strconv.ErrSyntax) or errors.Is(err, strconv.ErrRange).

2. When should I use Atoi versus ParseInt?

Atoi parses base-10 strings into int. Use ParseInt when you need another radix, an explicit int64/int32 width, or the same API shape as other Parse* calls.

3. What is the difference between Quote and QuoteToASCII?

Quote uses Go string escapes for non-printables. QuoteToASCII forces non-ASCII runes into \u or \U escapes so the result is ASCII-only.

4. Does ParseBool accept yes and no?

No. Only the values documented on ParseBool are accepted; yes and no return an error.

5. Why does Atoi fail on a string that looks numeric?

Leading or trailing spaces, thousands separators, and locale-specific decimal commas all make the syntax invalid. TrimSpace and normalize the string first, or parse with a scanner tailored to your format.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …