Interfaces In Go and how to use them

Interfaces In Go and how to use them

GoLang provides us a type called Interface type, which specifies a method set called its interface. Any type whose method set is a superset of the interface is said to implement the interface. So lets learn to use interfaces in Go.

You must be familiar with the interface keyword from Object-Oriented Language. The concept is the same, but its intended use in Go is different from how we have been using interfaces in our Object-Oriented languages like Java, C# and more. So before we deep dive into interfaces, lets clear up some concepts.

Is Go an Object Oriented language?

Yes and No. We can use Object oriented concepts in Go, but it’s not really intended to be used as an Object-Oriented language. From official go docs

Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is easy to use and in some ways more general. There are also ways to embed types in other types to provide something analogous—but not identical—to subclassing. Moreover, methods in Go are more general than in C++ or Java: they can be defined for any sort of data, even built-in types such as plain, “unboxed” integers. They are not restricted to structs (classes).
Also, the lack of a type hierarchy makes “objects” in Go feel much more lightweight than in languages such as C++ or Java.

How’s interfaces in Go are different from other Object Oriented languages?

From offical go lang docs

Object-oriented programming, at least in the best-known languages, involves too much discussion of the relationships between types, relationships that often could be derived automatically. Go takes a different approach.
Rather than requiring the programmer to declare ahead of time that two types are related, in Go a type automatically satisfies any interface that specifies a subset of its methods. Besides reducing the bookkeeping, this approach has real advantages

Enough said, lets start with coding

How to declare interfaces in Go?

An interface is a type just like struct e.g

Above is an example of Closer interface from inbuilt pkg io. Closer is an interface name that has one method Close in it that returns an error. It is usually considered to be a go-idiomatic way to have only one method in an interface. The bigger the interface, the weaker the abstraction

So how’s that different from Object-Oriented languages?

The difference lies in two key things, implementation and how its used.

Let’s see an example of how inbuilt os/file implements the inbuilt Closer interface.

That’s it! We don’t have to explicitly define that File implements Closer interface. So, if any method of a struct has the same name and signature of an interface, in that case, the struct implements the interface. It’s pretty much like Duck Typing(not exactly duck typing) which states If it looks like a duck, and it quacks like a duck, then it is a duck. In the above example, struct File has a method whose signature is just like of method Close in the interface Closer. That’s why File implements the interface Closer.

Okay, that’s fine, but what advantages do interfaces in Go have over Object–oriented interface?

From the top view, it seems like the same thing but Go interface gives us a lot more flexibility. Let’s understand it with an example.

Let’s say we want to close the file and if there is an error, log it

We can write a method like

So, this method closes the file and logs the error. As a general thumb rule in Go, your method should accept an interface and return a struct. In our case, we are not returning anything. We can call this method as

Focus here on defer Close(r). Now, let’s modify this Close method so that it accepts the inbuilt Closer interface.

So without any change, our main function will run since file implements Closer interface. But now lets make this method more interesting.

Let’s say you are establishing a connection to the database and when you are done, you want to close that connection. So we are talking about the package database/sql here. If we look closely, we see type Db has method Close that has the same signature as that of Closer. That means we can pass Db in this method. In source code, we can see

That means I can do something like

Note: defer Close(db) and Close (associated with *DB) both are different methods. defer Close() is a custom method that we created above that accepts Closer interface as an argument

Focus on defer Close(db). From the same method, I am able to close file and SQL con. But now, let’s make it more interesting!

Go provides Flexibility

As these structs were defined before writing out the Close method, let’s create a type that embedded a fake resource in it

Now we want to close this fake Resource also when we are done. So why don’t we take advantage of our Close method. If I write a method like this

Now, out FakeResource type implements Closer. Now I can pass the value of FakeResource in the Close method to close it. So that’s what godocs are saying as quoted above

Rather than requiring the programmer to declare ahead of time that two types are related, in Go a type automatically satisfies any interface that specifies a subset of its methods

This gives us a lot more flexibililty than conventional Object Oriented interfaces.

Difference in thinking philosophy

While using interfaces in Go, the design philosophy is different as that from conventional Object Oriented Languages. In Conventional languages, we first think of interfaces and design our classes around them, but in Go, we don’t need to declare interfaces ahead of time. Let’s break it down with an example.

We have a struct Square, and we have a method area defined.

Now lets say we want to have a method that will double the area of the square as under

We can call the above as

Now lets say we have one more requirement. We have one more struct rectangle and we need to find the double of Area for rectangle also. So we can create one interface here. I have named it Arear

So whole program will be like

Notice how we create interface Arear when needed. We didn’t think before about creating interface, but as when required

You can also run this example in go playground https://play.golang.org/p/pQIpBjzoCXV

That’s it . There are some further readings that I recommend

There are some further readings that I recommend

https://golang.org/doc/effective_go.html#interfaces

https://golang.org/ref/spec#Interface_types

https://gobyexample.com/interfaces

https://tour.golang.org/methods/9

https://golang.org/doc/faq#inheritance

https://www.ardanlabs.com/blog/2013/07/object-oriented-programming-in-go.html

Happy Coding!!!

Share This Post

Post Comment