Интерфейсы Go обычно принадлежат пакету, в котором используются значения типа интерфейса, а не пакету, реализующему эти значения. Реализующий пакет должен возвращать конкретные (обычно указатель или структура) типы: таким образом, новые методы могут быть добавлены к реализациям, не требуя обширного рефакторинга.
Не определяйте интерфейсы на имплементирующей стороне API «для создания mock'ов»; вместо этого спроектируйте API так, чтобы его можно было протестировать с использованием открытого API реальной реализации.
Не определяйте интерфейсы до того, как они будут использованы: без реалистичного примера использования слишком сложно понять, необходим ли интерфейс, не говоря уже о том, какие методы он должен содержать.
package consumer // consumer.go
type Thinger interface { Thing() bool }
func Foo(t Thinger) string { … }
package consumer // consumer_test.go
type fakeThinger struct{ … }
func (t fakeThinger) Thing() bool { … }
…
if Foo(fakeThinger{…}) == "x" { … }
// НЕ ДЕЛАЙТЕ ТАК!!!
package producer
type Thinger interface { Thing() bool }
type defaultThinger struct{ … }
func (t defaultThinger) Thing() bool { … }
func NewThinger() Thinger { return defaultThinger{ … } }
Вместо этого верните конкретный тип и позвольте потребителю создать mock реализации producer.
package producer
type Thinger struct{ … }
func (t Thinger) Thing() bool { … }
func NewThinger() Thinger { return Thinger{ … } }
Читайте также:
- Go Code Review Comments: введение, gofmt
- Эффективный Go: интерфейсы, преобразования
- Эффективный Go: интерфейсы и методы
Комментариев нет:
Отправить комментарий