Ответ
Интерфейс в 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. Это позволяет создавать кастомные типы ошибок.
Ответ 18+ 🔞
А, интерфейсы в Go! Ну это же, блядь, классика, ебать мои старые костыли. Представь себе такую хуйню: есть у тебя контракт, бумажка такая, где написано, что ты должен уметь крякать. И похуй, кто ты — утка, надувная резиновая игрушка или Колян после пятой рюмки. Если ты издаёшь «кря-кря», то ты, сука, автоматически становишься исполнителем этого контракта. Никаких заявлений, печатей, «имплементирует» кричать не надо. Молча сделал дело — и всё, ты в теме. Это и есть утиная типизация, ёпта. Если крякаешь — ты утка, и хуй с горы.
Вот смотри, примерчик, тут всё просто, как три копейки:
package main
import "fmt"
// Speaker — это наша бумажка-контракт. Говорит: «Хочу того, кто умеет говорить».
type Speaker interface {
Speak() string
}
// Dog — просто пёс, но он научился говорить «Гав!».
type Dog struct{}
func (d Dog) Speak() string { return "Woof!" }
// Cat — кошка, говорит «Мяу!». Никто не спрашивал, хочет ли она.
type Cat struct{}
func (c Cat) Speak() string { return "Meow!" }
// MakeSound — функция, которой похуй, кто перед ней. Лишь бы контракт выполнял.
func MakeSound(s Speaker) {
fmt.Println(s.Speak())
}
func main() {
d := Dog{}
c := Cat{}
MakeSound(d) // Выведет: Woof!
MakeSound(c) // Выведет: Meow!
}
Видишь? Никаких «я — собака, я — кошка». Функция MakeSound принимает любого, у кого есть метод Speak(). И всё, пиздец. Слабая связь, тестировать легко, подсовывай хоть хомяка, если он заговорит.
А теперь, внимание, сюрприз! Есть у нас такой пустой интерфейс — interface{}. Это, блядь, швейцарский нож, ёперный театр. В него можно запихнуть что угодно: число, строку, структуру, даже целую мартышку. Но потом, чтобы достать, надо проверять, что ты там, сука, такое положил. Типа, «эй, а ты точно int?». Иначе — runtime паника, и все в ротберунчик.
Композиция интерфейсов — это когда ты берёшь два простых контракта и склеиваешь в один посложнее. Например, io.Reader умеет читать, io.Writer — писать. А io.ReadWriter — это, блядь, универсальный солдат, который и читает, и пишет. Красота, да?
И наконец, ошибки. В Go ошибка — это не какой-то там магический exception, а просто тип, который удовлетворяет интерфейсу error. У него один метод — Error() string. Хочешь свою ошибку? Пожалуйста, создай тип, реализуй этот метод — и ты уже, сука, официальная ошибка. Никаких сложностей, всё прозрачно, как слёзы ребёнка.
Вот и вся магия. Интерфейсы в Go — это про то, чтобы не привязываться к конкретным типам, а договариваться о поведении. А если договорились — работаем. Не договорились — иди нахуй, в рот меня чих-пых.