# Methods and Pointers

> Source: https://learn-go.org/methods-and-pointers/
> Part of Learn Go, free to read.

A pointer holds the address of a value.

```go
x := 42
p := &x            // &x is "address of x"; p has type *int
fmt.Println(*p)    // 42 — *p is "the value at p"
*p = 100
fmt.Println(x)     // 100 — we changed x through p
```

Two operators: `&` takes an address, `*` follows one. Unlike C there is **no pointer arithmetic** — you cannot do `p++` — and there is no manual deallocation, because the garbage collector handles it. That removes most of what makes pointers dangerous elsewhere.

## Why pointers exist

Go passes everything by value. Without a pointer, a function receives a copy:

```go
func rename(u User)  { u.Name = "new" }    // modifies the copy
func rename2(u *User) { u.Name = "new" }   // modifies the original

user := User{Name: "old"}
rename(user)
fmt.Println(user.Name)     // "old"
rename2(&user)
fmt.Println(user.Name)     // "new"
```

The second reason is cost: copying a large struct on every call is wasted work.

## nil

The zero value of a pointer is `nil`. Dereferencing it panics:

```go
var p *User
fmt.Println(p == nil)      // true
fmt.Println(p.Name)        // panic: nil pointer dereference
```

This is Go's most common runtime crash. Anywhere a function can return a pointer, check it before use:

```go
user, err := findUser(id)
if err != nil {
    return err
}
// only safe past the error check
fmt.Println(user.Name)
```

`new(T)` allocates a zeroed `T` and returns a pointer to it, though a literal is more common:

```go
p := new(User)          // *User, zero valued
p := &User{Name: "Ada"} // more idiomatic
```

## Methods

A method is a function with a receiver — the thing before the name:

```go
type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}
```

```go
rect := Rectangle{Width: 3, Height: 4}
fmt.Println(rect.Area())     // 12
rect.Scale(2)                // Go takes &rect automatically
fmt.Println(rect.Area())     // 48
```

You can define methods on any type you declare in your package, not just structs:

```go
type Celsius float64

func (c Celsius) String() string {
    return fmt.Sprintf("%.1f°C", float64(c))
}

fmt.Println(Celsius(21.5))   // 21.5°C — fmt uses the String method
```

Implementing `String() string` makes your type print nicely everywhere. It is the single most useful method to add to a domain type.

## Value or pointer receiver

The decision you make on every method. The rules:

**Use a pointer receiver when:**
- the method modifies the receiver
- the struct is large (copying is wasteful)
- the type contains a `sync.Mutex` or anything else that must not be copied

**Use a value receiver when:**
- the type is small and immutable in practice (`time.Time`, a `Celsius`)

:::warn Be consistent across the whole type
Mixing receivers on one type causes a subtle problem: **only `*T` satisfies an interface when any method has a pointer receiver.**

```go
type Speaker interface{ Speak() string }

type Dog struct{ name string }
func (d *Dog) Speak() string { return d.name }

var s Speaker = Dog{}      // error: Dog does not implement Speaker
var s Speaker = &Dog{}     // fine
```

Pick one receiver style per type and use it for every method. When in doubt, use pointer receivers — it is the safer default and the more common convention.
:::

## Structs are copied on assignment

```go
a := Rectangle{Width: 1, Height: 2}
b := a              // a full copy
b.Width = 99
fmt.Println(a.Width) // 1 — unaffected
```

That is different from most object-oriented languages, where assignment copies a reference. It is usually what you want, and it is why you need `&` to share.

Note that a struct containing a slice or a map copies the *header*, not the underlying data — so both copies share the same backing array:

```go
type Team struct{ Members []string }
a := Team{Members: []string{"ada"}}
b := a
b.Members[0] = "grace"
fmt.Println(a.Members[0])    // "grace" — shared backing array
```

## Exercise

```go
package main

import "fmt"

type Counter struct {
	count int
}

func main() {
	// Add two methods to Counter:
	//   Increment() with a pointer receiver
	//   Value() int with a value receiver... then reconsider,
	//   and make BOTH pointer receivers for consistency.
	// Also add String() string so fmt prints "Counter(3)".
	c := Counter{}
	fmt.Println(c)
}
```

## Common questions

### Do I need `*` to call a method on a pointer?

No. Go dereferences automatically, so `p.Method()` works whether `p` is a `T` or a `*T`, and it takes the address for you when calling a pointer method on an addressable value. You only write `*p` when you want the value itself.

### Pointer or value receiver, if I am unsure?

Pointer. It is the more common convention, it avoids copying, and it means the method set works for interfaces without surprises. The main exception is small immutable value types where a value receiver reads more naturally.

### Are Go pointers dangerous like C pointers?

Much less so. There is no pointer arithmetic, no manual freeing, no dangling pointers after a free, and the garbage collector keeps anything reachable alive. The one real hazard left is dereferencing `nil`, which panics loudly rather than corrupting memory.
