В Go принято определять интерфейсы на стороне потребителя (consumer), а не рядом с реализацией. Это следствие неявной реализации интерфейсов:
// пакет storage - возвращает конкретный тип
package storage
type PostgresRepo struct { db *sql.DB }
func NewPostgresRepo(db *sql.DB) *PostgresRepo { ... }
func (r *PostgresRepo) GetUser(id int) (*User, error) { ... }
func (r *PostgresRepo) SaveUser(u *User) error { ... }
// пакет service - определяет только то, что ему нужно
package service
type UserGetter interface {
GetUser(id int) (*User, error)
}
func HandleGetUser(repo UserGetter, id int) { ... }
Почему так:
Исключение: стандартная библиотека определяет общепринятые интерфейсы (io.Reader, fmt.Stringer), потому что они используются повсеместно.