Экспортируем интерфейс вместо типа в Go
Когда тип существует лишь для реализации интерфейса (он никогда не станет экспортировать методы за пределы этого интерфейса), то отпадает надобность в том, чтобы экспортировать сам тип. Если же экспортировать только интерфейс, это даст понять, что у значения отсутствует какое-нибудь поведение кроме того, что описано в интерфейсе. Вдобавок к вышесказанному, исчезает необходимость в повторении документации на каждый случай общего метода.
В ситуации, описанной выше, конструктор обязан возвращать не тип реализации, а значение интерфейса. В качестве примера можно привести то, что в хэш-библиотеках adler32.New и crc32.NewIEEE возвращают тип интерфейса hash.Hash32. Таким образом, подстановка алгоритма CRC-32 для Adler-32 в Golang-программе потребует лишь изменения вызова конструктора, так как остальная часть кода является независимой от изменения алгоритма.
Такой подход дает возможность алгоритмам потокового шифра в разных пакетах crypto быть отделенными от блочных шифров, которые они объединяют в единое целое. При этом интерфейс Block в crypto/cipher-пакете указывает поведение блочного шифра, обеспечивающего шифрование одного блока данных. Далее, по аналогии с bufio-пакетом, пакеты шифров, реализующие данный интерфейс, смогут использоваться в целях построения потоковых шифров, которые представлены посредством интерфейса Stream, то есть без детальных знаний блока шифрования.
Давайте теперь посмотрим, как выглядят crypto/cipher-интерфейсы:
Ниже -- определение потока в режиме CTR-счетчика, превращающего блочный шифр в потоковый шифр. Важно отметить, что детали блочного шифра являются абстрагированными:
Итак, NewCTR используется не только и не столько для одного конкретного алгоритма шифрования и источника данных, сколько для любой реализация Block-интерфейса, да и любого Stream. А так как они возвращают значения интерфейса, то замена CTR-шифрования иными режимами шифрования будет считаться локализованным изменением. При этом вызовы конструктора следует отредактировать, но так как окружающий код обязан обрабатывать результат лишь как Stream, то и разница замечена не будет.
По материалам https://golang-blog.blogspot.com/.