Определение
интерфейс имеет то, что называется динамическим типом
Динамический тип означает, что он может содержать ссылку на различные типы (например, строка, INT, ...) и что он может меняться во время выполнения, тогда как статический тип проверяется во время компиляции и не может измениться.
Однако определение, данное книгой, подвергается сомнению. Согласно официальному сайту Голанга:
Некоторые люди говорят, что интерфейсы Go являются динамически типизированными, но это вводит в заблуждение. Они статически типизированы: переменная типа интерфейса всегда имеет один и тот же статический тип, и хотя во время выполнения значение, хранящееся в переменной интерфейса, может изменять тип, это значение всегда будет удовлетворять интерфейсу.
Source
Пример
Даже если интерфейс не действительно динамический тип, вот как их использовать.
Скажите, что у вас есть следующий интерфейс.
type Locker interface {
Lock()
Unlock()
}
Это на самом деле в Locker
из sync
пакета.
Теперь, если вы создадите две структуры, реализующие функции, определенные интерфейсом Locker. Другими словами, если вы выполняете договор Locker
, вы сможете использовать структуры Foo
и Bar
в качестве интерфейса Locker
.
type Foo struct {
A string
}
func (f *Foo) String() string {
return f.A
}
func (f *Foo) Lock() {
// ...
}
func (f *Foo) Unlock() {
// ...
}
type Bar struct {}
func (b *Bar) Lock() {
// ...
}
func (b *Bar) Unlock() {
// ...
}
Так дано определение вы дали:
тип интерфейса может содержать ссылку на экземпляр любого из типов, которые реализуют интерфейс (интерфейс имеет то, что называется динамический тип)
Это может быть переведено на:
шкафчике (интерфейс) станд e может содержать ссылку на экземпляр любого из типов, реализующих его контракт (например, Foo, Bar, ...).
Что в коде означает:
var lock Locker
lock = &Foo{"Foo"} // We assign an instance of type Foo to a Locker var
lock.Lock() // We can call all functions defined by the interface Locker
lock.Unlock()
lock.String() // This won't work because the Locker interface does not define the String() function, even though Foo implements it.
lock = &Bar{}
lock.Lock()
В приведенном выше примере мы можем видеть, что переменная lock
содержит ссылку на различные типы, но это не по-настоящему динамичным, так как условие для назначения типа для lock
заключается в том, что его тип соответствует договору Locker
. И эта часть определяется во время компиляции.
Почему это полезно?
Это сообщение объяснит, почему интерфейсы полезны лучше меня. https://softwareengineering.stackexchange.com/questions/108240/why-are-interfaces-useful
«Почему это полезно?» чувствует себя слишком широким вопросом. –
https://golang.org/ref/spec#Variables: «Статический тип (или просто тип) переменной - это тип, указанный в его объявлении, тип, указанный в новом вызове или составном литерале, или тип элемент структурированной переменной. Переменные типа интерфейса также имеют отдельный динамический тип, который является конкретным типом значения, назначенного переменной во время выполнения (если значение не является предопределенным идентификатором nil, который не имеет типа). динамический тип может меняться во время исполнения, но значения, хранящиеся в переменных интерфейса, всегда присваиваются статическому типу переменной ». –