Golang Interface Syntax, Composing, and Empty Interfaces

Golang Interface Syntax

In this blog, we will learn about Golang Interface Syntax.

Let’s see what we are going to learn in Golang Interface Syntax.

  • Syntax of Golang Interface
  • Basics of Golang Interface
  • Composing Interfaces
  • Empty Interface in Golang

Before learning Golang Interface make sure Basics of Golang are clear:

Golang Interface Syntax

type <Interface_name> interface { // Method – Initialization }

Example:

type geometry interface { area() float64 perimeter() float64 }

Golang struct vs interface

Structs in Golang allow us to define data and fields but Golang interface allows us to define behavior i.e methods.

Golang Interface Struct

Interfaces are named collection of method signatures.

Golang Interface helps us to implement polymorphism in our code.

Let’s make a geometry interface that will have two method signatures area() and perimeter().

Code:

type geometry interface {
	area() float64
	perimeter() float64
}

Now we will make structs for the shapes we want to find area and perimeter. In this example we will be making structs for rectangle and circle.

type rectangle struct {
	length  float64
	breadth float64
}

type circle struct {
	radius float64
}

The rectangle struct will have two fields that are length and breadth both of the float64 types (to hold floating-point values).

The circle struct has only one field i.e radius of float64 type.

Now let’s turn the method signatures defined in the geometry interface to methods for both circle and rectangle

func (r rectangle) area() float64 {
	return (r.length * r.breadth)
}

func (c circle) area() float64 {
	return (math.Pi * c.radius * c.radius)
}

func (r rectangle) perimeter() float64 {
	return 2 * (r.length + r.breadth)
}

func (c circle) perimeter() float64 {
	return (2 * math.Pi * c.radius)
}

This is the area and perimeter method for both rectangle and circle struct, as it takes object for linking that method to that struct.

The area and perimeter method return area and perimeter.

But, the area and perimeter method signature is in geometry interface and we cannot call it without instantiating geometry interface.

Let’s make a helper function that will take Shape and Geometry interface as parameters and will call the methods.

func measure(shape string, g geometry) {
	fmt.Println("Area of "+shape+": ", g.area())
	fmt.Println("Perimeter of "+shape+": ", g.perimeter())
}

The final work is to initialize structs with values in the main function and call measure function onto the initialized structs.

func main() {
	r := rectangle{length: 10.5, breadth: 4.2}
	c := circle{radius: 5.0}
	measure("Rectangle", r)
	measure("Circle", c)

}

The measure function takes shape of the struct and geometry instance, but when the measure function is called in the main function, passed values are the shape of the struct and the initialized struct and not the geometry interface, then how it works.

This is the real magic of the interface, the interface is only a collection of method signatures, the methods use the respective structs objects in order to retrieve field values from the structs and the interface helps us to map the fields.

If interfaces would not have been around, then we would have to call area and perimeter methods for both the structs separately.

Full Code of Go Interfaces:

package main

import (
	"fmt"
	"math"
)

type geometry interface {
	area() float64
	perimeter() float64
}

type rectangle struct {
	length  float64
	breadth float64
}

type circle struct {
	radius float64
}

func (r rectangle) area() float64 {
	return (r.length * r.breadth)
}

func (c circle) area() float64 {
	return (math.Pi * c.radius * c.radius)
}

func (r rectangle) perimeter() float64 {
	return 2 * (r.length + r.breadth)
}

func (c circle) perimeter() float64 {
	return (2 * math.Pi * c.radius)
}

func measure(shape string, g geometry) {
	fmt.Println("Area of "+shape+": ", g.area())
	fmt.Println("Perimeter of "+shape+": ", g.perimeter())
}

func main() {
	r := rectangle{length: 10.5, breadth: 4.2}
	c := circle{radius: 5.0}
	measure("Rectangle", r)
	measure("Circle", c)

}

Output:

Area of Rectangle: 44.1
Perimeter of Rectangle: 29.4
Area of Circle: 78.53981633974483
Perimeter of Circle: 31.41592653589793

Golang Composing Interface Syntax

Just like Golang Embedding, we can also embed two or more interfaces and group it into one, this is called Composing Interfaces in Go.

We can change the above example to make two more separate interfaces like area and perimeter interfaces and the geometry interface will group both the interfaces into one.(as Area and perimeter of any shape is just the Geometry of the shape).

type area interface {
	area() float64
}
type perimeter interface {
	perimeter() float64
}

type geometry interface {
	area
	perimeter
}

The rest of the code will be same and will work the same as above code.

Full Code for Composing interface in Go:

package main

import (
	"fmt"
	"math"
)

type area interface {
	area() float64
}
type perimeter interface {
	perimeter() float64
}

type geometry interface {
	area
	perimeter
}

type rectangle struct {
	length  float64
	breadth float64
}

type circle struct {
	radius float64
}

func (r rectangle) area() float64 {
	return (r.length * r.breadth)
}

func (c circle) area() float64 {
	return (math.Pi * c.radius * c.radius)
}

func (r rectangle) perimeter() float64 {
	return 2 * (r.length + r.breadth)
}

func (c circle) perimeter() float64 {
	return (2 * math.Pi * c.radius)
}

func measure(shape string, g geometry) {
	fmt.Println("Area of "+shape+": ", g.area())
	fmt.Println("Perimeter of "+shape+": ", g.perimeter())
}

func main() {
	r := rectangle{length: 10.5, breadth: 4.2}
	c := circle{radius: 5.0}
	measure("Rectangle", r)
	measure("Circle", c)

}

Output the same as the above code.

Golang Empty Interface Syntax

The interface that has no method signatures in it is known as empty interface.

Syntax:

var <interface_name> interface{}

The empty interface in Golang can hold any kind of value.

Example:

	var s interface{} = 17
	fmt.Printf("%v,%T", s, s)

Output:

17,int

Golang Empty interfaces have been used earlier in our code in the Golang switch statement where type function is used to find the type of the variable to match cases.

Example:

	var n interface{} = 1
	switch n.(type) {
	case int:
		fmt.Println("int")
	case float64:
		fmt.Println("float")
	case string:
		fmt.Println("String")

	}

Output:

int

Hope you like it!

Also, read Why Golang is called the future of Server-side language?

Learn more about Interface in Golang from the official Documentation.

Tags: , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *