Как в Go указать, что структура реализует интерфейс? Существует ли ключевое слово `implements`?

Ответ

В Go отсутствует явный синтаксис или ключевое слово (такое как implements в Java/PHP или : в C#) для указания, что структура реализует интерфейс.

Реализация интерфейса в Go неявная (implicit). Это означает, что если ваша структура (или любой другой тип) имеет все методы, объявленные в интерфейсе, с точно такими же сигнатурами (имена, параметры и возвращаемые значения), то компилятор автоматически считает, что этот тип реализует данный интерфейс.

Пример:

// 1. Определяем интерфейс
type Speaker interface {
    Speak() string
}

// 2. Определяем две разные структуры
type Dog struct{}
type Human struct{}

// 3. Реализуем метод Speak() для Dog
func (d Dog) Speak() string {
    return "Woof!"
}

// 4. Реализуем метод Speak() для Human
func (h Human) Speak() string {
    return "Hello!"
}

// 5. Теперь мы можем использовать Dog и Human там, где ожидается Speaker
func MakeSound(s Speaker) {
    fmt.Println(s.Speak())
}

func main() {
    d := Dog{}
    h := Human{}

    MakeSound(d) // Работает, т.к. Dog неявно реализует Speaker
    MakeSound(h) // Работает, т.к. Human неявно реализует Speaker
}

Зачем это нужно?

Такой подход способствует декаплингу (decoupling) — уменьшению связанности кода. Пакет, определяющий интерфейс, не должен знать о типах, которые его реализуют. И наоборот, пакет с типом не должен импортировать пакеты с интерфейсами, чтобы явно их "наследовать".

Как гарантировать реализацию?

Хотя реализация неявная, часто бывает полезно убедиться на этапе компиляции, что ваш тип действительно реализует нужный интерфейс. Для этого используется идиома с присваиванием нулевого значения переменной-заглушке _:

// Эта строка вызовет ошибку компиляции, если Dog не реализует Speaker.
// Обычно ее размещают сразу после определения типа.
var _ Speaker = Dog{}