How are interfaces implicitly satisfied in Go

Key takeaways:

  • Interfaces define a set of methods that a type must implement.

  • A type satisfies an interface implicitly by having the required methods, without needing an explicit declaration. This feature enhances flexibility, decouples components, and simplifies code.

  • Interfaces allow for polymorphism, making it easy to write generic functions.

  • Understanding and using interfaces effectively is crucial for Go developers to create maintainable and scalable applications.

Go is known for its simplicity and powerful features, one of which is its approach to interfaces. Unlike many programming languages, Go allows types to satisfy interfaces implicitly.

Implicit satisfaction of Interfaces

In Go, an interface is a type that specifies a set of method signatures. It is a way to define a contract for types, stating which methods they must implement. Unlike some other languages, Go interfaces are implicit, meaning a type automatically satisfies an interface if it implements the required methods without requiring explicit declarations.

Usage

Interfaces are declared using the type keyword followed by the interface name, interface keyword, and a set of method signatures inside curly braces.

type MyInterface interface {
Method1() int
Method2() string
}

In Go, interfaces are implicitly satisfied based on the method set of a type. A type is considered to implement an interface if it provides implementations for all the methods declared by that interface.

Example of implicit satisfaction

Let’s walk through an example to illustrate how interfaces are implicitly satisfied in Go:

package main
import "fmt"
// Defining an interface named Shape
type Shape interface {
Area() float64
Perimeter() float64
}
// Defining a type named Circle
type Circle struct {
Radius float64
}
// Implementing the methods for Circle to satisfy the Shape interface
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14 * c.Radius
}
// Defining a type named Rectangle
type Rectangle struct {
Length float64
Width float64
}
// Implementing the methods for Rectangle to satisfy the Shape interface
func (r Rectangle) Area() float64 {
return r.Length * r.Width
}
func (r Rectangle) Perimeter() float64 {
return 2*r.Length + 2*r.Width
}
// Function that takes any Shape and prints its Area and Perimeter
func PrintShapeInfo(s Shape) {
fmt.Printf("Area: %f, Perimeter: %f\n", s.Area(), s.Perimeter())
}
func main() {
// Creating a Circle and a Rectangle
circle := Circle{Radius: 5}
rectangle := Rectangle{Length: 4, Width: 6}
// Implicitly satisfying the Shape interface
// Both Circle and Rectangle types can be used wherever Shape is expected
PrintShapeInfo(circle)
PrintShapeInfo(rectangle)
}

Let’s now look at the code explanation step by step:

  1. We define an interface called Shape using Area() and Perimeter().

  2. We create two types, Circle and Rectangle.

  3. Both Circle and Rectangle have methods Area() and Perimeter() with the same signatures as those declared in the Shape interface.

  4. Since both types provide implementations for all the methods of the Shape interface, they are considered to implicitly satisfy the interface.

  5. The PrintShapeInfo function takes any type that satisfies the Shape interface and prints its area and perimeter.

  6. In the main function, we create instances of Circle and Rectangle and pass them to PrintShapeInfo, demonstrating how different types satisfying the same interface can be used interchangeably.

Implementing multiple interfaces

A type can satisfy multiple interfaces, allowing for rich behavior definition:

package main
import "fmt"
// Defining an interface named Shape
type Shape interface {
Area() float64
}
// Defining an interface named Colored
type Colored interface {
Color() string
}
// Defining a type named Circle
type Circle struct {
Radius float64
ColorName string // New field for color
}
// Implementing the methods for Circle to satisfy the Shape interface
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
// Implementing the Color method for Circle to satisfy the Colored interface
func (c Circle) Color() string {
return c.ColorName
}
// Function that takes Shape and prints its Area
func PrintShapeInfo(s Shape) {
fmt.Printf("Area: %f\n", s.Area())
}
// Function that takes Colored shape and prints its color
func PrintShapeColor(c Colored) {
fmt.Printf("Color: %s\n", c.Color())
}
func main() {
// Creating a Circle and a Rectangle
circle := Circle{Radius: 5, ColorName: "Red"}
// Implicitly satisfying the Shape interface
PrintShapeInfo(circle)
// Implicitly satisfying the Colored interface
PrintShapeColor(circle)
}

Advantages of implicit interface

The following are some of the advantages of the implicit interface:

  • Easily swap types that implement the same interface, adapting to changing requirements.

  • Promote cleaner code by allowing functions to operate on various types without specifics.

  • Maintain a clean codebase without explicit declarations, focusing on behavior.

  • Create mock types for straightforward testing without altering original implementations.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


What is the difference between explicit and implicit type?

Explicit type requires a formal declaration to implement an interface and implicit type satisfies an interface automatically by implementing its methods without declaration.


What is type assertions in Go?

A type assertion allows us to extract the underlying concrete value from an interface variable, assuming it holds the type:

value, ok := interface_type.(string)
  • interface_type is an interface for which we want to check the type assertion.

  • value contains the return type of the interface.

  • ok is a variable that holds any error that might occur during type assertion.


What is the difference between interfaces and structs in Go?

In Go, interfaces define a set of methods that a type must implement while structs, on the other hand, are concrete data types that encapsulate fields and can implement methods, including those defined by interfaces.


Free Resources

Copyright ©2025 Educative, Inc. All rights reserved