Interfaces: Simplifying Code and Boosting Flexibility

10 Feb 2024
12 minute read
Go interfaces allow you to define object behavior using a set of method signatures, providing a flexible and scalable way to write code. They promote abstraction and code reuse, making it a key aspect of Go programming.

Here are some typical Go interface examples.

  • io.Reader and io.Writer: these interfaces provide a standard way to read from and write to sources such as files, network connections, or in-memory buffers.
  • error: a built-in interface that represents an error condition in Go. Functions can return an error value, and clients can check whether an error occurred by checking if the error is nil.
  • sort.Interface: this interface defines the methods that a type needs to implement to be sortable by the standard library’s sorting functions.
  • http.Handler: this interface is used by the net/http package to represent HTTP handlers. It defines a single method, ServeHTTP, which takes an http.ResponseWriter and an http.Request as arguments.
  • fmt.Stringer: this interface provides a standard way to represent an object as a string. The fmt package’s Print and Println functions check if an object implements this interface and call its String method to get a string representation of the object.

Example

Imagine you have a program that can send notifications via email, SMS, or push notifications. You can define an interface called Notifier that defines a method such as Notify, and then have each of your notification types implement that interface. This allows you to write a generic function that can send notifications using any type of notifier.

package main

import "fmt"

type Notifier interface {
    Notify(message string)
}
type EmailNotifier struct {
    email string
}
func (e EmailNotifier) Notify(message string) {
    fmt.Printf("Sending email to %s: %s", e.email, message)
}
type SMSNotifier struct {
    phoneNumber string
}
func (s SMSNotifier) Notify(message string) {
    fmt.Printf("Sending SMS to %s: %s", s.phoneNumber, message)
}
type FCMNotifier struct {
    deviceToken string
}
func (f FCMNotifier) Notify(message string) {
    fmt.Printf("Sending fcm notification to %s: %s", f.deviceToken, message)
}
func main() {
    var n Notifier
    n = EmailNotifier{"[email protected]"}
    n.Notify("Important message")
    n = SMSNotifier{"555-123-4567"}
    n.Notify("Urgent message")
    n = FCMNotifier{"some-fcm-device-token"}
    n.Notify("Info message")
}

Try it on playground

In conclusion, Go interfaces are a powerful and versatile feature that enable you to define object behavior through a set of method signatures, promoting code abstraction and reuse. They are a fundamental aspect of Go programming, providing a flexible and scalable way to design and structure your code.