Ответ
Интерфейс в Go — это тип, который определяет набор методов (контракт). Любой тип, который реализует все методы интерфейса, автоматически (неявно) удовлетворяет этому интерфейсу. Основная цель интерфейсов — достижение полиморфизма и создание слабосвязанного (decoupled) кода, что упрощает тестирование и поддержку.
Пример:
package main
import "fmt"
// Speaker определяет поведение, которое мы ожидаем
type Speaker interface {
Speak() string
}
// Dog реализует интерфейс Speaker
type Dog struct{}
func (d Dog) Speak() string { return "Woof!" }
// Cat тоже реализует интерфейс Speaker
type Cat struct{}
func (c Cat) Speak() string { return "Meow!" }
// Функция принимает любой тип, удовлетворяющий интерфейсу Speaker
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
d := Dog{}
c := Cat{}
MakeSound(d) // Выведет: Woof!
MakeSound(c) // Выведет: Meow!
}
Ключевые особенности:
- Неявная реализация (Implicit Implementation): В отличие от языков вроде Java или C#, в Go не нужно явно указывать, что тип реализует интерфейс (ключевое слово
implements
отсутствует). Это известно как "утиная типизация": "Если это выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, и есть утка". - Пустой интерфейс (
interface{}
): Специальный случай интерфейса без методов. Может хранить значение абсолютно любого типа. Часто используется для работы с данными неизвестной структуры (например, при парсинге JSON), но требует проверки типа (type assertion) для безопасного использования. - Композиция интерфейсов: Интерфейсы можно встраивать друг в друга, создавая более сложные контракты из простых. Например, стандартный
io.ReadWriter
является композициейio.Reader
иio.Writer
. - Интерфейс
error
: В Go ошибки представлены через встроенный интерфейсerror
, у которого есть один методError() string
. Это позволяет создавать кастомные типы ошибок.