# Pointers

Course: [Go](https://www.devtutorials.ai/learn/go) · Section: Types and OOP
Source: https://www.devtutorials.ai/learn/go/types-and-oop/pointers

> Go pointers: memory addresses, the & and * operators, changing values through pointers, nil pointers, pass by value vs pointer parameters, and struct pointers.

## What Are Pointers?

**Pointer** = a variable that stores the **memory address** of another variable.

- A normal variable holds a value, like `70`.
- A pointer holds **where** a value lives, like `0xc000012080`.
- Through the pointer, you can read or change that value.

**Simple lesson:** a pointer is an arrow that points to another variable's box.

### A Real-World Example

Think of a student's locker at school.

- The **locker** holds books.
- The **locker number**, like "B-12", tells you where it is.
- If you give a friend your locker number, they can go and put a book inside.
- You did not give them the books. You gave them the **address**.

Now the mapping:

- **The locker** = a variable.
- **The books inside** = its value.
- **The locker number** = its memory address.
- **A note with the locker number** = a pointer.

Go has pointers, but it keeps them safe:

- no pointer arithmetic (you cannot do `p + 1`)
- memory is freed automatically by the garbage collector
- most of the time, you use pointers to let a function change a value, or to avoid copying big structs

## What You Will Learn

In this lesson, you will learn:

1. What pointers and memory addresses are, and why pointers are used.
2. The address operator `&` and the dereference operator `*`.
3. How to read and change values through a pointer, and what a nil pointer is.
4. How pass by value works, and how pointer parameters change original values.
5. How pointers work with structs.

## Pointer Fundamentals

### Memory Addresses

**Memory** = the computer's storage for running programs, like a long row of numbered lockers.

**Memory address** = the number of one locker. It is usually printed in hexadecimal, like `0xc000012080`.

```go runnable varies title="Print an address"
package main

import "fmt"

func main() {
	marks := 70
	fmt.Println(marks)
	fmt.Println(&marks)
}
```

- `&marks` gives the address of `marks`.
- The address is different on each run and each computer.

### Pointer Variables

**Pointer type** = `*T`, meaning "a pointer to a T".

- `*int` = a pointer to an `int`.
- `*string` = a pointer to a `string`.
- The zero value of every pointer is `nil`.

### Why Pointers Are Used

- **Let a function change a variable** that belongs to the caller.
- **Avoid copying** a big value, like a struct with many fields.
- **Share one value** between many parts of a program.
- **Say "no value"** with `nil`, for something that is optional.

**Simple lesson:** a pointer of type `*T` stores the address of a `T`.

## Pointer Operators

Step through the picture. Watch the arrow and the box.

### Address Operator (&)

**`&`** = "the address of". `&x` gives a pointer to `x`.

### Dereference Operator (*)

**Dereference** = follow the pointer to the value it points to.

**`*`** = "the value at". `*p` gives the value `p` points to.

```go runnable title="& and *"
package main

import "fmt"

func main() {
	marks := 70
	p := &marks
	fmt.Println(*p)
	*p = 85
	fmt.Println(marks)
	fmt.Println(p == &marks)
}
```

```text
70
85
true
```

- `p := &marks` makes `p` point to `marks`.
- `*p = 85` changes `marks`, through the pointer.
- `p == &marks` is true: both hold the same address.

**Simple lesson:** `&` makes a pointer, and `*` follows it to the value.

## Working with Pointers

### Dereferencing Pointers

Two pointers can point to the **same** box.

```go runnable title="Two pointers, one box"
package main

import "fmt"

func main() {
	score := 10
	a := &score
	b := &score
	*a += 5
	*b += 5
	fmt.Println(score, *a, *b)
}
```

```text
20 20 20
```

- Both `a` and `b` point to `score`.
- Changing through either one changes the same box.

### Modifying Values Through Pointers

You have seen `*p = 85`. Go also has `new`, which makes a fresh box that you reach only through a pointer.

**new(T)** = make a new zero-value `T` and give back a pointer to it.

```go runnable title="new()"
package main

import "fmt"

func main() {
	count := new(int)
	fmt.Println(*count)
	*count = 3
	*count++
	fmt.Println(*count)
}
```

```text
0
4
```

- `new(int)` makes a box holding `0`, and returns `*int`.
- This box has no name. You reach it only through `count`.

### Nil Pointers

**Nil pointer** = a pointer that points to nothing.

```go runnable title="Check for nil first"
package main

import "fmt"

func main() {
	var p *int
	fmt.Println(p == nil)
	if p != nil {
		fmt.Println(*p)
	} else {
		fmt.Println("p points to nothing")
	}
}
```

```text
true
p points to nothing
```

```go runnable expect-error title="Following a nil pointer"
package main

import "fmt"

func main() {
	var p *int
	fmt.Println(*p)
}
```

- Following a nil pointer stops the program.
- The message is `panic: runtime error: invalid memory address or nil pointer dereference`.
- Always check `p != nil` when a pointer might be empty.

A pointer you declare with `var p *int` is `nil` until you point it somewhere.

Give it an address first: `p = &x` or `p = new(int)`.

### No Pointer Arithmetic

- In C, you can do `p + 1` to move to the next box.
- Go does not allow this. It prevents a whole class of memory bugs.

**Simple lesson:** change values with `*p = ...`, make pointers with `&` or `new`, and check for `nil` before following one.

## Pointers in Functions

### Pass by Value

**Pass by value** = a function gets a **copy** of each argument. See **Functions**.

### Pointer Parameters

**Pointer parameter** = a parameter of type `*T`. The caller passes an address with `&`.

```go runnable title="Swap two values"
package main

import "fmt"

func swap(a, b *string) {
	*a, *b = *b, *a
}

func main() {
	first, second := "Asha", "Ravi"
	swap(&first, &second)
	fmt.Println(first, second)
}
```

```text
Ravi Asha
```

### Updating Original Values

- Use a pointer parameter when the function's **job** is to change the caller's value.
- Otherwise, prefer returning a new value. It is easier to read.
- Slices and maps already share their data, so you rarely need a pointer to them.

**Easy way to remember**

- Function needs to **change** your variable → pass `&x`, take `*T`.
- Function only **reads** it → pass `x`.

**Simple lesson:** Go passes copies, so pass a pointer when a function must change the original.

## Pointers and Structs

**Struct** = a group of named fields, like a student record. You will learn structs fully in **Structs and Methods**.

### Struct Pointers

```go runnable title="A pointer to a struct"
package main

import "fmt"

type Student struct {
	Name  string
	Marks int
}

func main() {
	s := Student{Name: "Meena", Marks: 80}
	p := &s
	p.Marks = 88
	fmt.Println(s.Marks)

	q := &Student{Name: "Kabir", Marks: 75}
	fmt.Println(q.Name, q.Marks)
}
```

```text
88
Kabir 75
```

- `&Student{...}` makes a struct and gives a pointer to it in one step.

### Accessing Struct Fields Through Pointers

- With a pointer `p` to a struct, write `p.Marks`.
- Go reads it as `(*p).Marks` for you.
- This automatic step is why struct pointers are easy to use.

```go runnable title="A function that updates a struct"
package main

import "fmt"

type Student struct {
	Name  string
	Marks int
}

func addGrace(s *Student, n int) {
	s.Marks += n
}

func main() {
	asha := Student{"Asha", 32}
	addGrace(&asha, 3)
	fmt.Println(asha)
}
```

```text
{Asha 35}
```

- Without the pointer, `addGrace` would change only a copy of `asha`.

**Simple lesson:** use `&Struct{...}` and `p.Field` to work with struct pointers. Go follows the pointer for you.

## TL;DR

1. **Pointer** = holds the address of a value. Type `*T`. Zero value `nil`.
2. **`&x`** = the address of `x`. **`*p`** = the value at `p`.
3. **`*p = v`** = change the value through the pointer.
4. **`new(T)`** = a new zero `T`, returned as `*T`.
5. **Nil pointer** = points to nothing. Following it panics. Check `p != nil`.
6. **Pass by value** = functions get copies. Pass `&x` to let them change `x`.
7. **Struct pointer** = `p := &Student{...}`, then `p.Marks` (Go adds the `*`).
8. **No pointer arithmetic** in Go.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| `var p *int` then `*p = 5` | A pointer comes with a box | A new pointer is nil | A nil pointer panic. Use `new(int)` or `&x`. |
| `addBonus(marks)` with a `*int` parameter | Go converts it | Pass the address: `&marks` | `cannot use marks (variable of type int) as *int` |
| `p = 85` to change the value | `=` goes through the pointer | Use `*p = 85` | A type error. |
| Changing a parameter to change the caller | Parameters are shared | They are copies | The caller's value does not change. |
| `p + 1` to move to the next value | Go has pointer arithmetic | It does not | A build error. |
| Pointers to slices and maps everywhere | They are always needed | Slices and maps already share data | Harder code for no gain. |
| Not checking `nil` | Pointers are always set | They may be nil | A crash at runtime. |

## Check Yourself

## Exercises

## What to Remember

- A pointer stores an address. Its type is `*T`, and its zero value is `nil`.
- `&x` gives a pointer. `*p` follows it.
- Functions get copies. Pass `&x` when a function must change `x`.
- Check `p != nil` before following a pointer that might be empty.
- With a struct pointer, `p.Field` works. Go adds the `*` for you.

Next: **Structs and Methods**. You will learn how to group related values into your own types, and give them behaviour.
