суббота, 26 января 2019 г.

Эффективный Go: экспорт интерфейса вместо типа

Если тип существует только для реализации интерфейса и никогда не будет экспортировать методы за пределами этого интерфейса, нет необходимости экспортировать сам тип. Экспорт только интерфейса дает понять, что значение не имеет какого-либо поведения сверх того, что описано в интерфейсе. Это также избавляет от необходимости повторять документацию на каждый случай общего метода.

В таких случаях конструктор должен возвращать значение интерфейса, а не тип реализации. Как пример, в хеш-библиотеках crc32.NewIEEE и adler32.New возвращают тип интерфейса hash.Hash32. Подстановка алгоритма CRC-32 для Adler-32 в Go программе требует только изменения вызова конструктора; остальная часть кода не зависит от изменения алгоритма.

Подобный подход позволяет алгоритмам потокового шифра в различных пакетах crypto быть отдельным от блочных шифров, которые они соединяют вместе. Интерфейс Block в пакете crypto/cipher указывает поведение блочного шифра, который обеспечивает шифрование одного блока данных. Затем по аналогии с пакетом bufio, пакеты шифров, которые реализуют этот интерфейс, могут быть использованы для построения потоковых шифров, представленных через интерфейс Stream, без знания деталей блока шифрования.

Интерфейсы crypto/cipher выглядят так:

type Block interface {
    BlockSize() int
    Encrypt(src, dst []byte)
    Decrypt(src, dst []byte)
}

type Stream interface {
    XORKeyStream(dst, src []byte)
}

Вот определение потока в режиме счетчика (CTR), который превращает блочный шифр в потоковый шифр; отметьте что детали блочного шифра абстрагированы:

// NewCTR возвращает поток, который шифрует/дешифрует, 
// используя данный блок в режиме счетчика. 
// Длина iv должна соответствовать размеру блока.
func NewCTR(block Block, iv []byte) Stream

NewCTR применяется не только для одного конкретного алгоритма шифрования и источника данных, но для любой реализация интерфейса Block и любого Stream. Потому что они возвращают значения интерфейса, замена CTR шифрование другими режимами шифрования является локализованным изменением. Вызовы конструктора должны быть отредактированы, но поскольку окружающий код должен обрабатывать результат только как Stream, он не заметит разницы.


Читайте также:


Комментариев нет:

Отправить комментарий