Sling Academy
Home/Golang/How Interfaces Work in Go: Implicit Implementation Explained

How Interfaces Work in Go: Implicit Implementation Explained

Last updated: November 26, 2024

Go is a statically typed, compiled language designed at Google that provides garbage collection, memory safety, and structural typing, among other useful features. One of the key features of Go is its powerful and flexible interface system. In this article, we will delve into how interfaces work in Go and how they promote the concept of implicit implementation.

Understanding Interfaces in Go

In Go, an interface is a type that specifies a contract: it defines a set of methods that a type must have to "implement" the interface. Interestingly, Go doesn’t require explicit specification when implementing an interface. This is known as implicit implementation, where if a type implements all the methods of an interface, it automatically satisfies the interface.

Basic Example

Let’s start with a simple example where we define a basic interface and implement it implicitly.

package main

import "fmt"

// Define the Animal interface
 type Animal interface {
     Speak() string
 }

// Define a Dog type
 type Dog struct{}

// Dog implements the Animal interface
 func (d Dog) Speak() string {
     return "Woof!"
 }

// Main function demonstrating the implementation
 func main() {
     var a Animal
     a = Dog{} // Dog implicitly implements Animal
     fmt.Println(a.Speak())
}

In this example, the Dog type has a Speak method. Because it fulfils the requirement of the Animal interface, it implicitly implements that interface without any explicit declaration.

Intermediate Example with Multiple Interfaces

Now, let’s explore a scenario where a type implements multiple interfaces:

package main

import "fmt"

// Define two interfaces
 type Walker interface {
     Walk() string
 }
 type Talker interface {
     Talk() string
 }

// Define a Human type
 type Human struct{}

// Human implements both Walker and Talker interfaces
 func (h Human) Walk() string {
     return "Walking"
 }

func (h Human) Talk() string {
     return "Talking"
 }

func main() {
     var w Walker
     var t Talker

     h := Human{}
     w = h
     t = h

     fmt.Println(w.Walk())
     fmt.Println(t.Talk())
}

In this example, the Human type implements both the Walker and Talker interfaces. Hence, it can be assigned to variables of both types without any explicit specification of implementation.

Advanced Example: Composability with Interfaces

One of Go’s unique features is its ability to create composable interface types. Below is an example demonstrating the composition of interfaces:

package main

import "fmt"

// Define Composdditolicial interface which is combination of all the interfaces
 type Speaker interface {
     Singer
     Dancer
}

// New Singer and Dancer interfaces
 type Singer interface {
     Sing() string
}

type Dancer interface {
     Dance() string
}

// Define Person type
 type Person struct{}

func (p Person) Sing() string {
     return "Singing"
 }

func (p Person) Dance() string {
     return "Dancing"
 }

func main() {
     var s Speaker
     s = Person{} // Person implements all methods required to fulfill Speaker
     fmt.Println(s.Sing())
     fmt.Println(s.Dance())
}

Here, the Speaker interface is a composite of Singer and Dancer interfaces. The Person type implements all methods required by Singer and Dancer, thus implicitly implementing Speaker as well.

Conclusion

Go's unique approach to interfaces simplifies many programming tasks. The implicit implementation model encourages cleaner and more readable code. Moreover, by allowing types to meet interface requirements through method implementation alone, Go fosters a more flexible and evolvable codebase. This, alongside with its composable interface capabilities, enables developers to create robust and scalable applications. By understanding and effectively leveraging Go interfaces, you can significantly improve the architecture and flexibility of your Go applications.

Next Article: Defining and Using Empty Interfaces (`interface{}`) in Go

Previous Article: Implementing Polymorphism Using Interfaces in Go

Series: Structs and Interfaces in Go

Golang

Related Articles

You May Also Like

  • How to remove HTML tags in a string in Go
  • How to remove special characters in a string in Go
  • How to remove consecutive whitespace in a string in Go
  • How to count words and characters in a string in Go
  • Relative imports in Go: Tutorial & Examples
  • How to run Python code with Go
  • How to generate slug from title in Go
  • How to create an XML sitemap in Go
  • How to redirect in Go (301, 302, etc)
  • Using Go with MongoDB: CRUD example
  • Auto deploy Go apps with CI/ CD and GitHub Actions
  • Fixing Go error: method redeclared with different receiver type
  • Fixing Go error: copy argument must have slice type
  • Fixing Go error: attempted to use nil slice
  • Fixing Go error: assignment to constant variable
  • Fixing Go error: cannot compare X (type Y) with Z (type W)
  • Fixing Go error: method has pointer receiver, not called with pointer
  • Fixing Go error: assignment mismatch: X variables but Y values
  • Fixing Go error: array index must be non-negative integer constant