Golang Working with interface¶
Note: To execute golang code online you can use https://play.golang.org/
What is an interface?¶
- An interface is defined as a custom datatype which contains set of unimplemented methods.
- The interface defines the behavior for similar type of objects.
- Go Interfaces are implemented implicitly
- To implement an interface, you just need to implement all the methods declared in the interface.
syntax to create an interface¶
type InterfaceName interface {
Method1() float64
Method2() int
}
woking with interface¶
Let's see a simple example to find the area and perimeter of a shape.
package main
import (
"fmt"
"reflect"
"math"
)
type Shape interface {
GetArea() float64;
GetPerimeter() float64;
}
type Circle struct {
Radius float64
}
func(c Circle) GetArea() float64 {
return math.Pi * math.Pow(c.Radius, 2)
}
func(c Circle) GetPerimeter() float64 {
return 2 * math.Pi * c.Radius
}
type Rectangle struct {
Length float64
Width float64
}
func(r Rectangle) GetArea() float64 {
return r.Length * r.Width
}
func(r Rectangle) GetPerimeter() float64 {
return 2 * (r.Length + r.Width)
}
func GetTotalArea(shapes ...Shape) float64{
sum := 0.0;
for _, obj:= range shapes{
sum = sum + obj.GetArea()
}
return sum
}
func main() {
var s Shape = Circle{Radius: 3}
fmt.Printf("Type: %s , Area: %f\n", reflect.TypeOf(s), s.GetArea())
s = Rectangle{Length: 10, Width: 20}
fmt.Printf("Type: %s , Area: %f\n", reflect.TypeOf(s), s.GetArea())
// find total area
totalArea := GetTotalArea(Circle{Radius: 3}, Rectangle{Length: 10, Width: 20})
fmt.Println("total area = ", totalArea)
}
Rectangle
and Circle
and an interface Shape
. - We also have a function GetTotalArea
which takes an array of objects of type interface and iterates through each and finds the total area. - To the function GetTotalArea
we can pass any object which has methods GetArea
and GetPerimeter
. - As we can see, we have written a generic function to calculate the total area irrespective of the object data type. It will be a complex if we didn't use an interface. - We use interfaces when we have a dynamic assignment of data objects which has the similar behaviour as the interface. using interface with switch statement¶
package main
import "fmt"
func PrintInterfaceType(x interface{}) {
switch x.(type) {
case bool:
fmt.Print(x.(bool))
case int:
fmt.Print(x.(int))
case float64:
fmt.Print(x.(float64))
case complex128:
fmt.Print(x.(complex128))
case string:
fmt.Print("string: ", x.(string))
case chan int:
fmt.Print(x.(chan int))
default:
fmt.Print("Unknown type")
}
fmt.Print("\n")
}
func main(){
var name interface{} = "Hello";
PrintInterfaceType(name)
// output: string: Hello
}
.(type)
to find the data type of the interface object. - We have a limitation for .(type)
syntax, we can only use it inside of a switch
case. - We have implemented the similar behaviour with switch
statement. finding type of data passed to interface¶
- In the above example we have seen how to get an actual type of interface object.
- But, we do have a similar package in golang which provides the similar functionality.
- By using package
reflect
, we can perform similar functionality easily. - Let's an example
package main
import "fmt"
import "reflect"
func main() {
var x interface{}
x = 3.14
t := reflect.TypeOf(x)
v := reflect.ValueOf(x) // x.(<type>)
fmt.Printf("x: type = %v, value = %v\n", t, v)
goo := x
fmt.Printf("goo: type = %T, value = %v\n", goo, goo)
x = &struct{ name string }{}
t = reflect.TypeOf(x)
v = reflect.ValueOf(x) // x.(<type>)
fmt.Printf("x: type = %v, value = %v\n", t, v)
hoo := x
fmt.Printf("hoo: type = %T, value = %v\n", hoo, hoo)
}
The above will produce the output something like below
x: type = float64, value = 3.14
goo: type = float64, value = 3.14
x: type = *struct { name string }, value = &{}
hoo: type = *struct { name string }, value = &{}
References: