Интерфейс тоже договор. Например, io.Reader
; у него есть специфическое поведение c, которое должны соблюдаться всеми реализациями, и использование его в качестве аргумента или возвращаемого типа документирует, какое поведение вы ожидаете, вместе с сигнатурами метода. Обратное также верно, поскольку для типов с перекрывающимися наборами методов, если у вас один и тот же метод, но вы не придерживаетесь определенного интерфейса, вы можете использовать другое имя интерфейса, чтобы различать guish два (который может не быть хорошим шаблоном в кодовой базе, но часто встречаются внешние интерфейсы, которые, возможно, придется дифференцировать).
Когда вы определяете какой-либо метод или функцию, используя io.Reader
, вы получаете возможность полагаться на все задокументированное поведение io.Reader
без необходимости документировать его каждый раз в своем собственном коде.
Go типы не являются вариантами, поэтому вы не можете объявить сигнатуру функции, которая удовлетворяет другой с закрытым интерфейсом. Если была функция func ReadFrom(r internal)
, вы не могли бы удовлетворить эту сигнатуру своей собственной func ReadFrom(r myInternal)
. В стандартной библиотеке есть множество примеров этого, которые вы не могли бы реализовать, если интерфейсы были частными; например
Наконец, хорошо известные интерфейсы также помогают просто читать и понимать код. io.Reader
- это известный интерфейс, который легко узнать в источнике. При встрече с myReader
вы не знаете, каково ожидаемое поведение, или даже каков набор методов, не обращаясь к документации.