DEV Community

Sheary Tan
Sheary Tan

Posted on

Brief Introduction to Interfaces in Go

As a new Gopher and a CodeNewbie who has never typed C++ or any strongly-typed languages before, I was having a hard time looking for some beginners-friendly resources about Interfaces in Go.

So here I am, decided to write one and doing my best to help any beginners.


What is Interfaces?

Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here. - Effective Go

Well it basically means interfaces is a type that has a bunch of methods.

Alright without talking too much, lets make things clear today.

Write some code

Aim: To implement two methods sum() and substr() which will then print out the sum and subtraction of two numbers.

1) Let's start with the setup

package main

import "fmt"

func main() {
}
Enter fullscreen mode Exit fullscreen mode

2) Then the type, here we have item1 and item2 with two numbers type float64 respectively:

package main

import "fmt"
Enter fullscreen mode Exit fullscreen mode
type item1 struct {
    num1, num2 float64
}

type item2 struct {
    num1, num2 float64
}

func main() {
}
Enter fullscreen mode Exit fullscreen mode

3) Now we need some instructions (methods) for the code to work:

package main

import "fmt"

type item1 struct {
    num1, num2 float64
}

type item2 struct {
    num1, num2 float64
}
Enter fullscreen mode Exit fullscreen mode
// Method
func (a item1) sum() float64 {
    return a.num1 + a.num2
}

// Method
func (a item1) substr() float64 {
    return a.num1 - a.num2
}

// Method
func (b item2) sum() float64 {
    return b.num1 + b.num2
}

// Method
func (b item2) substr() float64 {
    return b.num1 - b.num2
}
Enter fullscreen mode Exit fullscreen mode
func main() {
}
Enter fullscreen mode Exit fullscreen mode

Before continuing, let's get a better understanding on the method.

// Method
func (b item2) substr() float64 {
    return b.num1 - b.num2
}
Enter fullscreen mode Exit fullscreen mode

b is a reference to item2, which is the way we access num1 and num2 inside item2. Then we have the name substr(), the return type float64 and the return method.

4) Implementing result1 and result2 and print out the result:

package main

import "fmt"

type item1 struct {
    num1, num2 float64
}

type item2 struct {
    num1, num2 float64
}

// Method
func (a item1) sum() float64 {
    return a.num1 + a.num2
}

// Method
func (a item1) substr() float64 {
    return a.num1 - a.num2
}

// Method
func (b item2) sum() float64 {
    return b.num1 + b.num2
}

// Method
func (b item2) substr() float64 {
    return b.num1 - b.num2
}
Enter fullscreen mode Exit fullscreen mode
// Result 1 & Result 2
func result1(i item1) {
    fmt.Println("Sum: ", i.sum())
    fmt.Println("Substr: ", i.substr())
}

func result2(i item2) {
    fmt.Println("Sum: ", i.sum())
    fmt.Println("Substr: ", i.substr())
}

func main() {
    a := item1{num1: 10, num2: 5}
    b := item2{num1: 20, num2: 10}

    result1(a) 
    result2(b)
}

// Sum:  15
// Substr:  5
// Sum:  30
// Substr:  10
Enter fullscreen mode Exit fullscreen mode

Here we passed two variables: a and b to two functions: result1 and result2, and got the results.

But here is the problem:

Why do we need to write two functions (result1 and result2) that basically do the same thing?


So here is the thing you have been waiting for: Interfaces

5) Implementing interface. I mentioned before, interface is a type that has a collection of methods (function). It has both sum() and substr(), which are the names of the methods below:

package main

import "fmt"
Enter fullscreen mode Exit fullscreen mode
type math interface {
    sum() float64
    substr() float64
}
Enter fullscreen mode Exit fullscreen mode
type item1 struct {
    num1, num2 float64
}

type item2 struct {
    num1, num2 float64
}

// Method
func (a item1) sum() float64 {
    return a.num1 + a.num2
}

// Method
func (a item1) substr() float64 {
    return a.num1 - a.num2
}

// Method
func (b item2) sum() float64 {
    return b.num1 + b.num2
}

// Method
func (b item2) substr() float64 {
    return b.num1 - b.num2
}

func main() {

}
Enter fullscreen mode Exit fullscreen mode

6) Print out the result:

package main

import "fmt"

type math interface {
    sum() float64
    substr() float64
}

type item1 struct {
    num1, num2 float64
}

type item2 struct {
    num1, num2 float64
}

// Method
func (a item1) sum() float64 {
    return a.num1 + a.num2
}

// Method
func (a item1) substr() float64 {
    return a.num1 - a.num2
}

// Method
func (b item2) sum() float64 {
    return b.num1 + b.num2
}

// Method
func (b item2) substr() float64 {
    return b.num1 - b.num2
}
Enter fullscreen mode Exit fullscreen mode
func result(m math) {
    fmt.Println("Sum: ", m.sum())
    fmt.Println("Substr: ", m.substr())
}

func main() {
    a := item1{num1: 10, num2: 5}
    b := item2{num1: 20, num2: 10}

    result(a)
    result(b)
}

// Sum:  15
// Substr:  5
// Sum:  30
// Substr:  10
Enter fullscreen mode Exit fullscreen mode

So now we just have to include interface math with result, we will then be able to access sum() and substr() by calling it once in the main() section.
Here we are calling result once for both variables and got the same results!

Continue -> Empty interface

Thanks for reading my first ever published article!

Latest comments (1)

Collapse
 
tomxlawson profile image
tomxlawson

This is a clear example of the use of an interface. But, wouldn't it be easier just to replace these lines:

result(a) and result(b)

With these lines?

fmt.Println("Sum: ", a.sum(), "Substr: ", a.substr()) // Sum: 15 Substr: 5
fmt.Println("Sum: ", b.sum(), "Substr: ", b.substr()) // Sum: 30 Substr: 10

Then remove the "math" interface and the "result" function. This would result in less code for this example. But I guess interfaces are still useful if the code is more complex in this.