Type Conversion in Go
Why Go never converts types implicitly, and the explicit conversions you'll reach for constantly.
2 min read
Go is strict about types in a way that surprises people coming from JavaScript or Python: it never converts between types automatically, even between two numeric types that seem obviously compatible.
No implicit conversion, ever
var i int = 10
var f float64 = 3.5
result := i + f // compile error: mismatched types int and float64This looks harsh, but it's deliberate. Silent numeric coercion is a classic source of subtle bugs — precision loss, unexpected rounding, comparisons that silently do the wrong thing. Go forces you to say explicitly what you mean.
Explicit conversion syntax
Conversion looks like a function call using the target type's name:
var i int = 10
var f float64 = float64(i)
var f2 float64 = 3.9
var i2 int = int(f2) // 3 -- truncates, does not roundNotice int(f2) truncates toward zero rather than rounding. If you need rounding behavior, use math.Round first:
import "math"
rounded := int(math.Round(3.9)) // 4Converting between numeric types
var i32 int32 = 100
var i64 int64 = int64(i32)
var u uint = uint(i32) // fine as long as the value is non-negativeConverting a larger type into a smaller one (say, int64 into int8) can silently truncate the value if it doesn't fit — Go won't stop you, so it's worth being deliberate any time you're narrowing a numeric type.
Strings and numbers don't convert directly
This trips people up the most: you can't convert a number to a string with string(i) the way you might expect.
var i int = 65
s := string(i) // "A" -- interprets 65 as a Unicode code point, NOT "65"!string() on an integer treats it as a rune (a Unicode code point), not as "the digits of this number." To actually get "65", use the strconv package:
import "strconv"
s := strconv.Itoa(65) // "65"
n, err := strconv.Atoi("65") // 65, nilItoa ("integer to ASCII") converts an int to its string representation. Atoi ("ASCII to integer") does the reverse — and notice it returns two values: the parsed number, and an error that's non-nil if the string wasn't a valid number. Ignoring that error is a common beginner mistake; a later lesson covers Go's error-handling conventions in depth.
Converting other numeric formats
f, err := strconv.ParseFloat("3.14", 64)
b, err := strconv.ParseBool("true")
s := strconv.FormatFloat(3.14, 'f', 2, 64) // "3.14"Why this matters in practice
The extra explicitness costs a few keystrokes but pays off constantly: reading unfamiliar Go code, you always know exactly what type a value is and where it was converted, because every conversion is visible in the source. There's no hidden coercion table to memorize, unlike languages where "5" + 3 might produce "53" in one context and 8 in another depending on operator and types involved. In Go, that expression simply wouldn't compile until you were explicit about what you meant.
Test what you just learned
4 quick questions. Get all of them right to unlock the next lesson.
You can take the quiz without an account — logging in just lets your result count toward your progress.