# Structs and interfaces

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

## Structs

```go
type User struct {
    ID        string
    Name      string
    Email     string
    CreatedAt time.Time
}

u := User{ID: "1", Name: "Ada"}     // always use field names
```

Positional initialisation (`User{"1", "Ada", ...}`) compiles but breaks silently when someone adds a field. Use field names always.

## Methods

```go
func (u User) DisplayName() string {         // value receiver: gets a copy
    return u.Name
}

func (u *User) Rename(name string) {         // pointer receiver: can modify
    u.Name = name
}
```

The rule for choosing: **use a pointer receiver if the method modifies the receiver, or if the struct is large. Then use pointer receivers for all methods on that type**, for consistency — a type with mixed receivers is confusing and can behave surprisingly when stored in an interface.

## Embedding, not inheritance

```go
type Animal struct{ Name string }

func (a Animal) Speak() string { return a.Name + " makes a sound" }

type Dog struct {
    Animal              // embedded — no field name
    Breed string
}

d := Dog{Animal{"Rex"}, "Husky"}
d.Speak()               // promoted from Animal
d.Name                  // also promoted
```

This is composition with syntactic convenience, not inheritance. There is no virtual dispatch: if `Dog` defines its own `Speak`, `Animal`'s methods still call `Animal`'s version.

## Interfaces

An interface is a set of method signatures. A type satisfies it by having those methods — no `implements` keyword, no declaration.

```go
type Writer interface {
    Write(p []byte) (n int, err error)
}
```

Anything with that method is a `Writer`. That includes types in packages that have never heard of yours.

### Define interfaces where they are used

This is the idiom that most distinguishes good Go from Go written like Java. The **consumer** declares what it needs:

```go
// in package report — small, local, exactly what this function uses
type UserStore interface {
    FindByID(ctx context.Context, id string) (*User, error)
}

func Generate(ctx context.Context, store UserStore, id string) (*Report, error) {
    u, err := store.FindByID(ctx, id)
    ...
}
```

The database package just exposes a concrete type. It never imports `report`, never declares an interface, and nothing changes when you add a test double — you pass a struct with one method.

:::tip Keep interfaces small
"The bigger the interface, the weaker the abstraction." The standard library's most-used interfaces have one method: `io.Reader`, `io.Writer`, `error`, `fmt.Stringer`. If yours has eight, it is a description of one implementation rather than an abstraction.
:::

### Type assertions and switches

```go
if s, ok := v.(fmt.Stringer); ok {
    fmt.Println(s.String())
}

switch x := v.(type) {
case string:  fmt.Println("string", x)
case int:     fmt.Println("int", x)
default:      fmt.Println("something else")
}
```

### The nil interface trap

```go
type MyError struct{}
func (e *MyError) Error() string { return "boom" }

func find() error {
    var e *MyError = nil
    return e             // an interface holding a nil pointer is NOT nil
}

if find() != nil {       // this is true
    // ...
}
```

An interface value has two parts — a type and a value — and it is only `nil` when both are. Return a literal `nil`, never a typed nil pointer. This is the most famous Go gotcha and it still appears in generated code.

## Common questions

### Should methods use pointer or value receivers?

Pointer if the method modifies the receiver or the struct is large; value for small immutable types. Then keep it consistent across the whole type — mixing them causes surprises when the type is stored in an interface, because only the pointer type satisfies the interface in that case.

### Where should interfaces be defined?

In the package that consumes them, not the package that implements them. That keeps the interface small (it lists exactly what one consumer needs) and it means implementations do not have to import anything to satisfy it.

### How do I do inheritance?

You do not, and after a while you stop wanting to. Embedding covers code reuse; interfaces cover polymorphism. What is missing is virtual dispatch through a base class, which is usually better expressed as an interface anyway.
