Урок объясняет, что такое интерфейсы в Go, как они позволяют описывать поведение вместо типов, как работает неявная реализация, чем отличаются value и pointer receivers, и как использовать type assertion для получения реального типа.
Интерфейсы - это способ описывать поведение, а не конкретные данные. Они позволяют писать гибкий код, который работает с разными типами, если они реализуют нужные методы. Go использует неявную реализацию интерфейсов, что делает их мощными и простыми одновременно.
Интерфейс определяет набор методов, которые должны быть у типа, чтобы он считался реализацией этого интерфейса.
Пример:
type Shape interface {
Area() float64
}
Интерфейс Shape говорит: «любой тип, у которого есть метод
Area() float64, является фигурой».
В Go не нужно явно указывать, что тип реализует интерфейс.
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
Теперь Rectangle автоматически считается реализацией Shape.
Функция может принимать любой тип, который реализует интерфейс:
func PrintArea(s Shape) {
fmt.Println(s.Area())
}
Использование:
rect := Rectangle{10, 5}
PrintArea(rect)
Тип может реализовать интерфейс через: - value receiver --- работает с копией структуры; - pointer receiver --- работает с указателем, может изменять данные.
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
Можно передавать: - значение (rect), - указатель (&rect).
func (r *Rectangle) Scale(f float64) {
r.Width *= f
r.Height *= f
}
Тогда метод доступен только через указатель.
*MyInterface) --- они
бессмысленны.Иногда нужно преобразовать интерфейс обратно в конкретный тип:
var s Shape = Rectangle{10, 5}
rect, ok := s.(Rectangle)
if ok {
fmt.Println("Width:", rect.Width)
}
Используется, чтобы выполнять код в зависимости от конкретного типа, скрытого за интерфейсом:
func Describe(x interface{}) {
switch v := x.(type) {
case int:
fmt.Println("int:", v)
case string:
fmt.Println("string:", v)
default:
fmt.Println("unknown")
}
}
type Resetter interface {
Reset()
}
type Player struct {
Health int
}
func (p *Player) Reset() {
p.Health = 100
}
Использование:
p := &Player{Health: 30}
p.Reset() // здоровье сброшено
type assertion и type switch позволяют работать с реальными
типами.