Go Interfaces


Interfaces in Go provide a way to specify the behavior of an object. They’re a powerful tool for achieving abstraction and polymorphism, allowing you to write more flexible and reusable code. Unlike some languages, interfaces in Go are implicitly satisfied. This means you don’t explicitly declare that a type implements an interface. If a type has the methods defined by the interface, it automatically implements it.

Defining an Interface

An interface is defined using the interface keyword, followed by the interface name and a set of method signatures.

type Speaker interface {
    Speak() string
}

This Speaker interface defines a single method Speak() which returns a string.

Implementing an Interface

Let’s create two types, Dog and Cat, that both implement the Speaker interface:

type Dog struct {
    name string
}

func (d Dog) Speak() string {
    return "Woof! My name is " + d.name
}

type Cat struct {
    name string
}

func (c Cat) Speak() string {
    return "Meow! My name is " + c.name
}

Notice that neither Dog nor Cat explicitly states that it implements Speaker. They simply define the Speak() method with the correct signature.

Using Interfaces

The power of interfaces comes from the ability to use them as generic types. Here’s a function that accepts anything that implements the Speaker interface:

func MakeSpeak(s Speaker) {
    fmt.Println(s.Speak())
}

func main() {
    dog := Dog{name: "Fido"}
    cat := Cat{name: "Whiskers"}

    MakeSpeak(dog) // Output: Woof! My name is Fido
    MakeSpeak(cat) // Output: Meow! My name is Whiskers
}

The MakeSpeak function doesn’t care whether it’s given a Dog, a Cat, or any other type, as long as it implements the Speaker interface.

Empty Interface

The empty interface interface{} is a special case. It has no methods, meaning every type in Go implicitly implements it. This is useful when you want to write functions that can operate on values of any type.

func PrintAnything(v interface{}) {
    fmt.Println(v)
}

func main() {
    PrintAnything(5)       // Output: 5
    PrintAnything("hello") // Output: hello
    PrintAnything(true)    // Output: true
}

Type Assertions

When using the empty interface, you might need to determine the underlying type of a value. This is done using a type assertion:

func PrintType(v interface{}) {
    if s, ok := v.(string); ok {
        fmt.Println("It's a string:", s)
    } else {
        fmt.Println("It's not a string")
    }
}

Interfaces in Go are a crucial part of the language, facilitating code reuse, flexibility, and strong typing. Understanding their implicit nature and versatile applications is key to writing effective Go programs.