Advertisement
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 { // 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 the Golang interface allows us to define behavior i.e methods.
Golang Interface Struct
Interfaces are named collections 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 rectangles and circles.
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 are in the geometry interface and we cannot call it without instantiating geometry interface.
Let’s make a helper function that will take the 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 the 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
The perimeter of Rectangle: 29.4
Area of Circle: 78.53981633974483
The perimeter of Circle: 31.41592653589793
Golang Composing Interface Syntax
Just like Golang Embedding, we can also embed two or more interfaces and group them 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 the same and will work the same as the 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 an empty interface.
Syntax:
var 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 the 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.