Интерфейсы в Go
Теория: Встраивание интерфейсов
Когда приложение растёт, количество интерфейсов увеличивается. Сначала кажется, что всё просто: есть интерфейс для чтения, для записи, для закрытия ресурсов. Но со временем появляются функции, которые требуют сразу несколько таких интерфейсов.
Например, функция, которая копирует данные из одного места в другое, должна принимать два интерфейса — для чтения и для записи:
С первого взгляда это нормально, но когда таких параметров становится много, функции превращаются в длинные списки аргументов. Так легко перепутать порядок, забыть нужный интерфейс или передать неправильный объект. Например, если после записи надо ещё и закрыть ресурс, функция примет уже три параметра:
С ростом проекта таких функций становится всё больше. Поддерживать код с длинными списками интерфейсов неудобно, появляются ошибки.
Чтобы упростить код, несколько интерфейсов объединяют в один новый, который включает методы всех вложенных интерфейсов. Этот приём называется композицией интерфейсов.
Композиция позволяет создавать более сложные интерфейсы на основе простых, не дублируя методы и не усложняя структуру кода. В Go это стандартный и широко используемый подход. Например, стандартная библиотека Go содержит интерфейсы io.Reader и io.Writer. Их можно объединить в интерфейс io.ReadWriter:
Теперь функцию копирования можно переписать так:
Вместо двух параметров теперь один, и работать с функцией проще.
Другой пример — объединение интерфейсов для записи и закрытия ресурса:
Так функции становятся короче, понятнее и удобнее в использовании. Передавать один интерфейс вместо двух или трёх — меньше шансов ошибиться.
Этот способ объединения интерфейсов широко применяется в Go. Он помогает структурировать код, сокращать количество параметров функций и снижать вероятность ошибок. Особенно полезен он в работе с файлами, сетевыми соединениями и тестированием, где часто нужны похожие наборы методов.
Объединение интерфейсов не усложняет реализацию, а наоборот — упрощает использование и поддержку кода.


