7. Type conversions
Go will not mix types behind your back. Add an int to a float64 and it
won't quietly convert one for you — it's a compile error. That feels strict
at first, but it means the surprising bugs of implicit conversion simply
can't happen. When you want a conversion, you ask for it explicitly.
No implicit mixing
Run this and read the error, then we'll fix it:
package main
import "fmt"
func main() {
count := 3 // int
price := 4.5 // float64
total := count * price // error: mismatched types
fmt.Println(total)
}
Go stops you because count is an int and price is a float64, and it
won't guess which one you meant to change.
Conversion syntax: T(value)
To convert, wrap the value in the target type like a function call:
float64(count), int(price), string(...). Here's the fix:
package main
import "fmt"
func main() {
count := 3
price := 4.5
total := float64(count) * price // now both are float64
fmt.Printf("%.2f\n", total)
}
Converting truncates, it doesn't round
Turning a float64 into an int throws away the fractional part — it
truncates toward zero, it does not round:
package main
import "fmt"
func main() {
a := 3.9
b := -3.9
fmt.Println(int(a)) // 3, not 4
fmt.Println(int(b)) // -3
}
Note we convert variables here. Converting a fractional constant
directly — int(3.9) — is actually a compile error in Go (constant 3.9
truncated to integer): the compiler won't silently drop the .9 from a
literal. Truncation only happens when you convert a value that's already a
float at runtime.
If you want rounding, that's a deliberate step (add 0.5 before converting, or
use math.Round) — the conversion alone never rounds for you.
Integer division is its own trap
This isn't a conversion, but it bites people constantly. Divide two integers and you get an integer result — the remainder is discarded — before any float ever enters the picture:
package main
import "fmt"
func main() {
fmt.Println(7 / 2) // 3 (integer division)
fmt.Println(float64(7) / 2) // 3.5
fmt.Println(float64(7 / 2)) // 3 — too late! divided as ints first
}
The order matters: convert before dividing, not after. float64(7 / 2)
does the integer division first, then converts the 3.
Strings are not numbers
A very common beginner mistake: converting an int to a string with
string(65) does not give you "65". It interprets the number as a
Unicode code point — 65 is the letter A:
package main
import "fmt"
func main() {
fmt.Println(string(rune(65))) // "A", not "65"
}
To turn a number into its text form, you use the strconv package (or
fmt.Sprintf), which we'll see properly in the standard-library module:
package main
import (
"fmt"
"strconv"
)
func main() {
n := 65
text := strconv.Itoa(n) // "Itoa" = integer to ASCII
fmt.Println(text + text) // "6565" — string concatenation
viaFmt := fmt.Sprintf("%d", n)
fmt.Println(viaFmt)
}
Your turn
You have total := 7 and people := 2 (both int). Compute the share each
person gets as a float64 and print it to 2 decimals — exactly:
Each person pays 3.50
Watch the integer-division trap: convert before you divide.
package main
import "fmt"
func main() {
total := 7
people := 2
// compute the per-person share as a float64 and print it
}
package main
import "fmt"
func main() {
total := 7
people := 2
share := float64(total) / float64(people)
fmt.Printf("Each person pays %.2f\n", share)
}
That closes out types. Next module: making decisions and repeating work — Go's control flow.