Интерфейсы в Go
В этом посте речь пойдет об интерфейсах — очень важной и интересной фиче языка Go. Абстрактные типы данных Для того чтобы лучше понять интерфейсы, полезно разобраться с понятием абстрактных типов данных. Упрощённо абстрактные типы данных можно определить как типы, у которых не может существовать собственных значений. Справедливый вопрос: а зачем такие типы тогда нужны? АТД в первую очередь определяет требования к «обычному» типу данных. Если тип соответствует требованиям, то говорят, что он является реализацией для АТД, а значит, может быть использован в переменных, полях и сигнатурах, где в качестве типа был указан реализуемый АТД. Например, над любыми числами можно совершать любые, за некоторыми исключениями, арифметические операции. Следовательно, можно объявить абстрактный тип Число, разными реализациями которого будут натуральные, целые, рациональные, вещественные и комплексные числа. Если не важны специфические свойства какого-либо множества чисел, то гораздо удобнее оперировать более абстрактным понятием числа. Интерфейсы Интерфейс является частным случаем, а в языке Go — по сути единственным представителем семейства АТД. Интерфейсы используются, чтобы описать, каким набором методов должна обладать его реализация. Это полезно, когда нас интересует только поведение некоторой сущности, но совсем не интересуют детали реализации. Это в свою очередь помогает снизить связность компонентов приложения и упрощает сопровождение кода. Давайте взглянем на стандартную библиотеку языка. Она содержит много интерфейсов, которые похожи на то, что авторы языка называют хорошим и идиоматичным интерфейсом. Одни из самых используемых — знаменитая тройка Writer, Reader, Closer, интерфейсы из пакета io: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 type Writer interface { Write(p []byte) (n int, err error) } // ... type Reader interface { Read(p []byte) (n int, err error) } // ... type Closer interface { Close() error } В данных трёх типах можно увидеть идиоматику интерфейсов в Go:...