# Data Types

Course: [Go](https://www.devtutorials.ai/learn/go) · Section: Go Foundations
Source: https://www.devtutorials.ai/learn/go/foundations/data-types

> Go's number types, strings, booleans, bytes and runes, zero values, nil, type inference, and converting between types with T(x) and strconv.

## What Are Data Types?

**Data type** = the kind of value a variable can hold.

The type tells Go two things:

- **what** the value is, like a number or text
- **how much memory** the box needs

For example:

- `92` is a whole number: type `int`
- `91.5` is a number with a decimal point: type `float64`
- `"Asha"` is text: type `string`
- `true` is a yes or no answer: type `bool`

**Simple lesson:** every value in Go has a type, and the type decides what you can do with it.

### A Real-World Example

Think of the school's report card form.

- The **Name** box only takes letters.
- The **Marks** box only takes numbers.
- The **Passed?** box only takes a tick or a cross.

If someone writes "ninety" in the Marks box, the office sends the form back.

Now the mapping:

- **Each box** = a variable.
- **What the box accepts** = its type.
- **Sending the form back** = Go stopping your program before it runs.

Go is **statically typed**.

**Static typing** = Go checks every type before the program runs.

- Mistakes are found on your computer, not by your users.
- A variable keeps the same type for its whole life.

## What You Will Learn

In this lesson, you will learn:

1. The number types: integers, floats and complex numbers.
2. The `string`, `bool`, `rune` and `byte` types.
3. **Zero values**: what a variable holds before you give it a value.
4. What `nil` means.
5. How Go guesses a type for you (type inference).
6. How to convert a value from one type to another.

## Numeric Types

Go has three families of number types.

### Integer Types

**Integer** = a whole number, like `-3`, `0` or `250`.

Each integer type has a size in **bits**.
**Bit** = the smallest piece of computer memory: a `0` or a `1`.

Click each type and compare its size and range.

Look at two things:

- **More bits** = a bigger range of numbers.
- **`uint` types** are never negative, so their range goes higher.

| Type | Size | Range |
|---|---|---|
| `int8` | 8 bits | -128 to 127 |
| `int16` | 16 bits | -32,768 to 32,767 |
| `int32` | 32 bits | about -2.1 billion to 2.1 billion |
| `int64` | 64 bits | about -9.2 × 10¹⁸ to 9.2 × 10¹⁸ |
| `uint8` | 8 bits | 0 to 255 |
| `uint16` | 16 bits | 0 to 65,535 |
| `uint32` | 32 bits | 0 to about 4.2 billion |
| `uint64` | 64 bits | 0 to about 1.8 × 10¹⁹ |

### int, uint and uintptr

- **`int`** = 64 bits on most computers today. Use it by default.
- **`uint`** = the same size as `int`, but never negative.
- **`uintptr`** = an integer big enough to hold a memory address. Only low-level code uses it.

```go runnable title="Integer types"
package main

import (
	"fmt"
	"math"
)

func main() {
	var students int = 42
	var floor int8 = -2
	var pages uint = 350
	fmt.Println(students, floor, pages)
	fmt.Println(math.MaxInt8, math.MinInt8, math.MaxUint8)
}
```

```text
42 -2 350
127 -128 255
```

- The `math` package has the limits of each type, like `math.MaxInt8`.

### Overflow: When a Number Is Too Big

**Overflow** = a value goes past the largest number its type can hold.

Press **Play** to see it happen.

- Go does **not** stop the program on overflow while it runs.
- The number wraps around, like a car's trip meter going from 999 to 000.
- So choose a type big enough for your numbers. `int` is usually safe.

### Float Types

**Float** = a number with a decimal point, like `3.14` or `-0.5`.

- `float32` keeps about 7 correct digits.
- `float64` keeps about 15 correct digits.

```go runnable title="float32 vs float64"
package main

import "fmt"

func main() {
	var a float32 = 1.0 / 3
	var b float64 = 1.0 / 3
	fmt.Println(a)
	fmt.Println(b)
}
```

```text
0.33333334
0.3333333333333333
```

- `float64` keeps many more digits, so its answer is more exact.
- Go uses `float64` when you write `x := 2.5`.

### Complex Types

**Complex number** = a number with a real part and an imaginary part, written like `3 + 4i`.

- `complex64` uses two `float32`s.
- `complex128` uses two `float64`s.
- `real(z)` gives the real part. `imag(z)` gives the imaginary part.

```go runnable title="A complex number"
package main

import "fmt"

func main() {
	z := complex(3, 4)
	fmt.Println(z, real(z), imag(z))
}
```

```text
(3+4i) 3 4
```

**Simple lesson:** use `int` for whole numbers and `float64` for decimals, unless you have a special reason.

## Text and True/False Types

### The string Type

**String** = a piece of text, written in double quotes.

- `"Green Valley School"` is a string.
- `""` is an **empty string**: text with nothing in it.
- `+` joins two strings.
- `len()` gives the length in **bytes**.

```go runnable title="Strings"
package main

import "fmt"

func main() {
	first := "Asha"
	last := "Rao"
	full := first + " " + last
	fmt.Println(full, len(full))
}
```

```text
Asha Rao 8
```

You will learn much more in **Strings**.

### The bool Type

**bool** = a value that is only `true` or `false`.

- Use it for yes or no questions.
- Comparisons like `marks >= 35` give a `bool`.

```go runnable title="Booleans"
package main

import "fmt"

func main() {
	marks := 72
	passed := marks >= 35
	isMonitor := false
	fmt.Println(passed, isMonitor)
}
```

```text
true false
```

### The byte Type

**byte** = another name for `uint8`. It holds one byte of data, from 0 to 255.

- Files and network data are made of bytes.
- An English letter like `'g'` fits in one byte.

### The rune Type

**rune** = another name for `int32`. It holds one **Unicode character**.

**Unicode** = a list that gives every character in every language its own number.

- `'A'` is number 65.
- `'अ'` (Hindi) is number 2309.
- Single quotes `' '` make a rune. Double quotes `" "` make a string.

```go runnable title="byte and rune"
package main

import "fmt"

func main() {
	var b byte = 'g'
	var r rune = 'अ'
	fmt.Println(b, string(b))
	fmt.Println(r, string(r))
}
```

```text
103 g
2309 अ
```

- Printing a `byte` or `rune` shows its **number**.
- `string(...)` turns it back into a character.

Type some text below and compare bytes and runes.

- **English letters** use 1 byte each.
- **Hindi letters and emoji** use 3 or 4 bytes each.
- So `len()` counts bytes, not characters.

**Simple lesson:** `string` is text, `bool` is true or false, `byte` is one byte, and `rune` is one character.

## Zero Values

**Zero value** = the value Go puts in a variable when you do not give one.

Go never leaves a variable empty by accident.

| Type | Zero value |
|---|---|
| Numbers (`int`, `float64`, ...) | `0` |
| `bool` | `false` |
| `string` | `""` (empty text) |
| Pointer | `nil` |
| Slice | `nil` |
| Map | `nil` |
| Interface (like `error`) | `nil` |

```go runnable title="Zero values"
package main

import "fmt"

func main() {
	var marks int
	var price float64
	var passed bool
	var name string
	var p *int
	var list []int
	var ages map[string]int
	var err error
	fmt.Println(marks, price, passed)
	fmt.Printf("%q\n", name)
	fmt.Println(p, list, ages, err)
}
```

```text
0 0 false
""
<nil> [] map[] <nil>
```

- `%q` prints the string inside quotes, so you can see it is empty.
- An empty slice prints as `[]`, an empty map as `map[]`.
- Pointers, slices and maps come in **Pointers**, **Slices** and **Maps**.

**Simple lesson:** a new variable always starts with its zero value: `0`, `false`, `""` or `nil`.

## nil

**nil** = "nothing here yet". It is the zero value for pointers, slices, maps, channels, functions and interfaces.

Think of an empty parking slot with a number painted on it.

- The slot exists.
- No car is parked there yet.

`nil` is that empty slot.

### Where nil Appears

- **nil pointer:** a pointer that points to nothing. See **Pointers**.
- **nil slice:** a list with no storage yet. It still works with `len()` and `append`.
- **nil map:** you can read from it, but writing to it crashes the program.
- **nil interface:** for example, an `error` that is `nil` means "no error".

```go runnable title="nil values"
package main

import "fmt"

func main() {
	var list []int
	var ages map[string]int
	var err error
	fmt.Println(list == nil, len(list))
	fmt.Println(ages == nil, ages["Asha"])
	fmt.Println(err == nil)
}
```

```text
true 0
true 0
true
```

- A nil slice has length `0`.
- Reading a missing key from a nil map gives the zero value.
- `err == nil` is how Go programs check "did anything go wrong?". You will use it in **Error Handling**.

Writing to a nil map crashes the program: `panic: assignment to entry in nil map`.

You will learn to create maps safely in **Maps**.

**Simple lesson:** `nil` means "no value yet", and it belongs to pointers, slices, maps and interfaces.

## Type Inference

**Type inference** = Go works out the type from the value, so you do not have to write it.

### Type Inference with :=

| You write | Go picks |
|---|---|
| `count := 10` | `int` |
| `price := 9.5` | `float64` |
| `name := "Ravi"` | `string` |
| `ok := true` | `bool` |
| `letter := 'A'` | `rune` |
| `z := 2 + 3i` | `complex128` |

```go runnable title="See the type Go picked"
package main

import "fmt"

func main() {
	count := 10
	price := 9.5
	letter := 'A'
	fmt.Printf("%T %T %T\n", count, price, letter)
}
```

```text
int float64 int32
```

- `%T` prints the **type** of a value.
- `rune` prints as `int32`, because they are the same type.

### Explicit Types vs Inference

**Explicit type** = you write the type yourself.

- **Inference:** `price := 9.5`. Short, and Go picks `float64`.
- **Explicit:** `var price float32 = 9.5`. Use it when you want a type Go would not pick.
- Most Go code uses inference inside functions.

**Simple lesson:** Go guesses the type from the value, and you write it yourself only when you need a different one.

## Type Conversion

**Type conversion** = making a value of one type from a value of another type.

Go **never** converts types by itself.
You must ask, by writing the type like a function: `float64(x)`.

### Explicit Conversion

Run this. It adds an `int` and a `float64`.

```go runnable expect-error title="Mixing types is not allowed"
package main

import "fmt"

func main() {
	marks := 45
	bonus := 2.5
	fmt.Println(marks + bonus)
}
```

- Go stops with an error like `invalid operation: marks + bonus (mismatched types int and float64)`.
- Go will not mix an `int` and a `float64`.
- Fix: convert one of them, like `float64(marks) + bonus`.

### Numeric Conversion

Press **Play** and watch each conversion.

- `float64(x)` turns a number into a float.
- `int(x)` cuts off everything after the decimal point: `int(price)` is `9` when `price` is `9.99`.
- `int(9.99)` with the number typed in directly does not build, because Go sees the decimals would be lost.
- Dividing two `int`s also drops the decimal part: `7 / 2` is `3`.

```go runnable title="Integer division vs float division"
package main

import "fmt"

func main() {
	fmt.Println(7 / 2)
	fmt.Println(float64(7) / 2)
	price := 9.99
	fmt.Println(int(price))
}
```

```text
3
3.5
9
```

### String Conversion

Numbers and text need the **strconv** package (string conversion).

| Function | Does | Example |
|---|---|---|
| `strconv.Itoa(n)` | int to string | `strconv.Itoa(99)` gives `"99"` |
| `strconv.Atoi(s)` | string to int | `strconv.Atoi("42")` gives `42` |
| `strconv.ParseFloat(s, 64)` | string to float64 | `"3.75"` gives `3.75` |
| `strconv.ParseBool(s)` | string to bool | `"true"` gives `true` |
| `fmt.Sprint(x)` | anything to string | `fmt.Sprint(12)` gives `"12"` |

```go runnable title="Text to number and back"
package main

import (
	"fmt"
	"strconv"
)

func main() {
	n, err := strconv.Atoi("42")
	fmt.Println(n+1, err)

	_, err = strconv.Atoi("forty")
	fmt.Println(err)

	label := "Roll no: " + strconv.Itoa(17)
	fmt.Println(label)
}
```

```text
43 <nil>
strconv.Atoi: parsing "forty": invalid syntax
Roll no: 17
```

- `Atoi` gives back **two** values: the number, and an error.
- If the text is not a number, the error says so.
- Always check the error when the text comes from a user.

`string(65)` does **not** give `"65"`. It gives `"A"`, the character with number 65.

To turn a number into its digits, use `strconv.Itoa(65)`.

**Easy way to remember**

- Number to number: `float64(x)`, `int(x)`
- Number to text: `strconv.Itoa(n)`
- Text to number: `strconv.Atoi(s)`, and check the error

**Simple lesson:** Go never mixes types by itself, so you convert with `T(x)` for numbers and `strconv` for text.

## TL;DR

1. **Data type** = the kind of value a variable holds.
2. **Integers** = `int`, `int8` ... `int64`, `uint`, `uint8` ... `uint64`, `uintptr`.
   - Use `int` by default.
   - **Overflow** = going past the limit wraps around.
3. **Floats** = `float32`, `float64`. Use `float64`.
4. **Complex** = `complex64`, `complex128`.
5. **string** = text. **bool** = `true` or `false`.
   - **byte** = `uint8`. **rune** = `int32`, one Unicode character.
6. **Zero value** = `0`, `false`, `""` or `nil`.
   - **nil** = "nothing yet" for pointers, slices, maps and interfaces.
7. **Type inference** = `x := 2.5` makes a `float64`.
8. **Conversion** = `float64(x)`, `int(x)`, `strconv.Itoa`, `strconv.Atoi`.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| `marks + 2.5` with an `int` | Go mixes number types | Convert first: `float64(marks) + 2.5` | `mismatched types int and float64` |
| `int(price)` to round | `int()` rounds | `int()` cuts off the decimals | You get `9`, not `10`. |
| `7 / 2` for 3.5 | Division always keeps decimals | Two ints give an int | You get `3`. |
| `string(65)` for `"65"` | It makes the digits | It makes the character `"A"` | Wrong text. Use `strconv.Itoa`. |
| Ignoring the `Atoi` error | The text is always a number | Check `err` | A silent `0` instead of a number. |
| `int8` for big numbers | Any int type will do | Pick a type big enough | Overflow wraps to a wrong number. |
| `'Hello'` for text | Single quotes make strings | Single quotes make one rune | A build error. |

## Check Yourself

## Exercises

## What to Remember

- Every value has a type. Go checks types before the program runs.
- Use `int` for whole numbers, `float64` for decimals, `string` for text, `bool` for yes or no.
- `byte` is one byte. `rune` is one character.
- New variables start at their zero value: `0`, `false`, `""` or `nil`.
- Go never converts types for you. Use `float64(x)`, `int(x)`, `strconv.Itoa` and `strconv.Atoi`.

Next: **Operators**. You will learn how to do maths, compare values and combine true or false answers.
