Go Interfaces Tutorial
Welcome all, in this tutorial we are going to be taking a look at interfaces within the Go programming language.
By the end of this tutorial, we’ll have covered the following topics:
- The Basics of Interfaces
 - Defining Your Own Interfaces
 
There will be a number of challenges at the end of this tutorial that you are free to try and complete on your own machine to try and validate some of the topics we have covered in this tutorial. If you appreciate this method of learning then please feel free to let me know in the comments section below!
Github Source Code - The full source code for this tutorial can be found here: TutorialEdge/Go-Interfaces-Tutorial
Basic Example
If you are new to Go, you may be seeing interface{} a lot in code snippets and
tutorials. This can be fairly daunting seeing this at first if you don’t know
what interfaces are in Go and what they are used for.
Typically, if you see a function or a method that expects an empty interface, then you can typically pass anything into this function/method.
Let’s see an example of this in action:
package main
import (
    "fmt"
)
func myFunc(a interface{}) {
    fmt.Println(a)
}
func main() {
    var my_age int
    my_age = 25
    myFunc(my_age)
}
If we then go to run this then we should see that it runs successfully and prints out our integer value:
$ go run main.go
25
Why is this Useful?
By defining a function that takes in an interface{}, we essentially give
ourselves the flexibility to pass in anything we want. It’s a Go programmers way
of saying, this function takes in something, but I don’t necessarily care about
its type.
Defining Interfaces
So, what are interfaces? Why do we use them within Go? Well by defining an
interface in Go, we essentially define a contract. If we define a type based off
this interface then we are forced to implement all of the functions or methods
defined within that interface type.
Say, for example, we wanted to define an interface for a Guitarist. We could
define our interface to include a PlayGuitar() function like so:
type Guitarist interface {
  // PlayGuitar prints out "Playing Guitar"
  // to the terminal
  PlayGuitar()
}
With our Guitarist interface defined, we could define a BaseGuitarist and an
AcousticGuitarist struct which implements the Guitarist interface.
package main
import "fmt"
type Guitarist interface {
    // PlayGuitar prints out "Playing Guitar"
    // to the terminal
    PlayGuitar()
}
type BaseGuitarist struct {
    Name string
}
type AcousticGuitarist struct {
    Name string
}
func (b BaseGuitarist) PlayGuitar() {
    fmt.Printf("%s plays the Bass Guitar\n", b.Name)
}
func (b AcousticGuitarist) PlayGuitar() {
    fmt.Printf("%s plays the Acoustic Guitar\n", b.Name)
}
func main() {
    var player BaseGuitarist
    player.Name = "Paul"
    player.PlayGuitar()
    var player2 AcousticGuitarist
    player2.Name = "Ringo"
    player2.PlayGuitar()
}
Should we wish, we could then create an array of type Guitarist which could
store both our BaseGuitarist and AcousticGuitarist objects.
var guitarists []Guitarist
guitarists = append(guitarists, player)
guitarists = append(guitarists, player2)
Return Values
In real-world examples, we would typically have more complex functions within our interfaces that featured return values. In Go, we can define these interfaces like so:
type Employee interface {
    Name() string
    Language() string
    Age() int
    Random() (string, error)
}
Satisfying Interfaces
Say we wanted to create an array of all Employee’s in the firm. Within this
array, we’d want all of our Engineers.
Now, in order for this to work, we’d need our Engineer type to satisfy the
Employee interface or it will not allow us to compile our program:
package main
type Employee interface {
    Language() string
    Age() int
    Random() (string, error)
}
type Engineer struct {
    Name string
}
func (e Engineer) Language() string {
    return e.Name + " programs in Go"
}
func main() {
    // This will throw an error
    var programmers []Employee
    elliot := Engineer{Name: "Elliot"}
    // Engineer does not implement the Employee interface
    // you'll need to implement Age() and Random()
    programmers = append(programmers, elliot)
}
Conclusion
So, within this tutorial, we have successfully managed to uncover what interfaces are within Go and how we can implement them within our own Go-based programs.
Hopefully, you found this tutorial useful and if you did then please let me know in the comments section below!
Note - If you want to keep track of when new Go articles are posted to the site, then please feel free to follow me on twitter for all the latest news: @Elliot_F.