# Interface compliance at compile-time in Go

# Interfaces

Imagine having an `interface` called `Runner` that looks like this:

```go
type Runner interface {
	Run() error
}
```

And a `struct` called `Worker` that you want to implement the mentioned interface. What you need to do? Ofc the only thing required is to add a `Run` function according to the interface:

```go
type Worker struct {
}

func (w Worker) Run() error {
	return nil
}
```

Voilà! Now your `Worker` struct implements the `Runner` interface.

The whole program now looks like this:

```go
package main

import "fmt"

type Runner interface {
	Run() error
}

type Worker struct {
}

func (w Worker) Run() error {
	return nil
}

func main() {
	w := Worker{}

	fmt.Println("worker", w)
}
```

You can run your program and everything is fine:

```bash
➜  interfaces git:(main) ✗ go run main.go
worker {}
```

# Interface Mutation → Problem

Okay, but what will happen if you change the `Runner` `interface`?

```go
type Runner interface {
	Run() error
	Stop() error
}
```

Well, you run the program and… nothing happens. Program runs successfully, but `Worker` is no longer compliant with the `Runner` interface, bc it’s missing the `Stop` function:

```bash
➜  interfaces git:(main) ✗ go run main.go
worker {}
```

# Compile-time Compliance

How to be sure that your struct implements the interface at a complie-time? That’s easy! You just need to add this line:

```go
var _ Runner = (*Worker)(nil)
```

What it does, you ask?

* The underscore `_` is used only as a blank identifier, means to ignore the value.
    
* The `Runner` is the `interface` that we want to check.
    
* And the right side of the assignement is a type conversion of `nil` to a `pointer` of the `Worker` struct.
    

Thanks to this we enforce at the compile-time that the given type (`Worker`) implements the `interface` (`Runner`).

Having the `main` packages like this (with the missing `Stop` function in the `Worker`):

```go
package main

import "fmt"

type Runner interface {
	Run() error
	Stop() error
}

var _ Runner = (*Worker)(nil)

type Worker struct {
}

func (w Worker) Run() error {
	return nil
}

func main() {
	w := Worker{}

	fmt.Println("worker", w)
}
```

When we try to run this program:

```bash
➜  interfaces git:(main) ✗ go run main.go
# command-line-arguments
./main.go:10:16: cannot use (*Worker)(nil) (value of type *Worker) as Runner value in variable declaration: *Worker does not implement Runner (missing method Stop)
```

We got a compile-time error.

Let’s fix this quickly by adding a missing `Stop` function:

```go
func (w Worker) Stop() error {
	return nil
}
```

And we’re good:

```bash
➜  kiss-samples git:(main) ✗ go run main.go
worker {}
```

That’s it! Hope you like it and use it in your own projects!

# Sources

* Code samples: [https://github.com/flashlabs/kiss-samples/tree/main/interfaces](https://github.com/flashlabs/kiss-samples/tree/main/interfaces)
