Интерфейсы в Go — это абстрактные типы, определяющие набор методов, которые должны быть реализованы конкретными типами. Внутренне они представлены двумя основными структурами: iface и eface.
iface используется для интерфейсов, которые требуют реализации методов. Её определение выглядит примерно так:
type iface struct {
tab *itab // Указатель на таблицу методов (itab)
data unsafe.Pointer // Указатель на конкретные данные
}
tab *itab — содержит метаинформацию о типе и таблицу методов.data unsafe.Pointer — указатель на значение конкретного типа, реализующего интерфейс.itab — это ключевая структура, связывающая интерфейс и конкретный тип:
type itab struct {
inter *interfacetype // Метаинформация о интерфейсе
_type *_type // Метаинформация о конкретном типе
hash uint32 // Копия _type.hash для быстрых проверок типов
_ [4]byte // Выравнивание
fun [1]uintptr // Таблица методов (гибкий массив)
}
inter *interfacetype — описывает сам интерфейс (например, его имя и сигнатуры методов)._type *_type — описывает конкретный тип, который реализует интерфейс.hash — кэш хеша типа, используется для проверок типа в type assertion.fun — массив указателей на методы конкретного типа, соответствующие методам интерфейса.Пустой интерфейс не требует методов, поэтому его представление проще:
type eface struct {
_type *_type // Метаинформация о типе
data unsafe.Pointer // Указатель на данные
}
iface используется для интерфейсов с методами.eface — для пустого интерфейса interface{}.itab (или используется кэшированный), связывающий интерфейс и конкретный тип.iface или eface:
data указывает на значение.tab (для iface) ссылается на соответствующий itab.var r io.Reader // Интерфейс
r = os.Stdout // Присваивание значения
b := r.(*os.File) // Type assertion (использует itab.hash для проверки)
iface (с методами) и eface (пустой интерфейс).itab связывает интерфейс и конкретный тип, храня таблицу методов.itab и проверки во время выполнения.interface{}) работают через eface и не требуют таблицы методов.