Basic data types
Every built-in type, why there are so many integer sizes, and what to actually use.
- Choose the right built-in type for a count, an id, a decimal and a money amount.
- Predict the output of overflowing an
int8or auint8. - Explain why
0.1 + 0.2is not exactly0.3for float64 variables.
What a type is, and why there are so many
A type tells Go two things: what kind of value a variable holds, and what you are allowed to do with it. int holds whole numbers and can be added; string holds text and can be joined. The compiler checks this before your program runs, so passing a string where an int is expected never reaches production.
Go's built-in types are called basic types. There are more of them than in a language like Python because Go lets you say how big a number is, 8 bits or 64. That matters when you are talking to a database, a file format, or another machine.
The full list
| Type | Holds | Zero value |
|---|---|---|
bool | true or false | false |
string | immutable bytes, usually UTF-8 text | "" |
int, uint | whole numbers, 64-bit on 64-bit platforms | 0 |
int8 int16 int32 int64 | signed, exact size | 0 |
uint8 uint16 uint32 uint64 | unsigned, exact size | 0 |
byte | alias for uint8 — one byte of data | 0 |
rune | alias for int32 — one Unicode code point | 0 |
float32, float64 | decimals | 0 |
complex64, complex128 | complex numbers (you will not use these) | 0 |
Which one do I actually use?
- `int` for counting anything. It is the default, it is 64-bit on the servers and laptops you will deploy to, and using
int32"to save memory" on a loop counter saves nothing. - `int64` for database ids and anything crossing a wire format where the size must be fixed.
- `float64` for decimals.
float32only when you have a specific reason, like graphics. - Never a float for money.
0.1 + 0.2 != 0.3in binary floating point. Use integer cents (the smallest currency unit), or a decimal library. - `byte` for raw data, `rune` for characters. They are the same thing as
uint8andint32, but the alias tells the reader your intent.
Overflow wraps around, silently
var x int8 = 127x++fmt.Println(x) // -128 — it wrapped. No panic, no warning.var u uint8 = 0u--fmt.Println(u) // 255// the math package has the limitsfmt.Println(math.MaxInt64, math.MinInt64)Mixing types needs a conversion
Go will not add an int to a float64 for you, and turning a number into text needs the strconv package. Both get a whole lesson of their own: Type conversion.
Try it yourself
package mainimport "fmt"func main() { var small int8 = 127 small++ fmt.Println("int8 overflow:", small) // -128, silently var count int = 3 var price float64 = 2.50 var name string = "tea" var paid bool var initial byte = 'T' var letter rune = 'é' fmt.Println(count, price, name, paid) // paid is false: its zero value fmt.Println(initial, letter) // 84 233 — both are just numbers fmt.Printf("%c %c\n", initial, letter) // T é — %c prints them as characters fmt.Println(0.1+0.2 == 0.3) // true here, but only because constants are exact a, b := 0.1, 0.2 fmt.Println(a+b == 0.3) // false: float64 variables are not}intfor counting,int64for ids,float64for decimals, never a float for money.- Overflow wraps silently. That is why every conversion between sizes is explicit.
byteisuint8andruneisint32. The aliases exist to show intent.- Every type starts at its zero value:
0,""orfalse.
int for when it does not.int8 and a uint8 on purpose. Then declare one variable of each type in the table without a value, and print them all on one line to see every zero value.- 1Print
math.MaxInt64andmath.MinInt64, then add one to each. - 2Add 0.1 and 0.2 as float64 and print the result. That is why money is not a float.
- 3Store the price of three items as whole cents in an
int64, add them, and print the total as dollars and cents with/ 100and% 100.