Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Interfaces for Polymorphism | Encapsulation and Interfaces
Struct-Based Design in Go

bookInterfaces for Polymorphism

Swipe to show menu

Go interfaces provide a powerful mechanism for achieving polymorphism and decoupling in backend design. An interface in Go is a type that specifies a set of method signatures. Any type that implements those methods automatically satisfies the interface, without needing explicit declarations. This allows you to write functions and components that operate on abstractions, not concrete types, leading to more modular and testable code.

The syntax for declaring an interface uses the type keyword, followed by the interface name and the interface keyword. Inside the curly braces, you define the required method signatures. For instance, you might define an interface for sending notifications, where any type that implements the Notify method satisfies the interface.

Go developers commonly use interfaces to abstract dependencies, such as repositories, services, or external APIs. This enables you to swap implementations easily and write unit tests using mocks or stubs. It is idiomatic in Go to define small, focused interfaces that describe a single behavior, rather than large, catch-all interfaces.

notifier.go

notifier.go

copy
123456789101112131415161718192021222324252627282930313233343536373839
package main import "fmt" // Notifier interface defines a single method Notify type Notifier interface { Notify(message string) } // EmailNotifier implements Notifier type EmailNotifier struct { EmailAddress string } func (e EmailNotifier) Notify(message string) { fmt.Printf("Sending email to %s: %s\n", e.EmailAddress, message) } // SMSNotifier implements Notifier type SMSNotifier struct { PhoneNumber string } func (s SMSNotifier) Notify(message string) { fmt.Printf("Sending SMS to %s: %s\n", s.PhoneNumber, message) } // SendAlert accepts any Notifier and uses it to send a message func SendAlert(n Notifier, message string) { n.Notify(message) } func main() { email := EmailNotifier{EmailAddress: "user@example.com"} sms := SMSNotifier{PhoneNumber: "+1234567890"} SendAlert(email, "Your order has shipped!") SendAlert(sms, "Your code is 123456.") }

By using interfaces, you can decouple your code from specific implementations. In the example above, the SendAlert function only depends on the Notifier interface, not on EmailNotifier or SMSNotifier directly. This means you can add new types of notifiersโ€”such as push notifications or webhooksโ€”without changing the SendAlert function. Interfaces also make it easier to write tests, since you can pass in mock implementations that record calls or simulate failures. This flexibility is a core strength of Go's approach to polymorphism and leads to backend code that is easier to maintain, extend, and test.

question mark

Which of the following is an advantage of using interfaces in Go backend services?

Select all correct answers

Everything was clear?

How can we improve it?

Thanks for your feedback!

Sectionย 2. Chapterย 3

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

Sectionย 2. Chapterย 3
some-alt