IIUC, ваш вопрос не о пакетах, а сводится к тому, является ли функция (или метод)
может быть приведен к другой функции, которая принимает аргументы с эквивалентными, но
не тот же тип интерфейса.
Примерно так: ( Go Playground )
package main
type I1 interface{}
func f1(x I1) {}
func main() {
f := (func(interface{}))(f1)
f(nil)
}
Ошибка компиляции: ./g.go:8:26: cannot convert f1 (type func(I1)) to type func(interface {})
Ответ, кажется, нет, потому что Го не считает func (I1)
эквивалентно func (interface{})
. Go spec говорит это
Тип функции обозначает набор всех функций с одинаковыми параметрами и типами результатов.
Типы func (I1)
и func (interface{})
не принимают одинаковые параметры, даже если
I1
определяется как interface{}
. Ваш код не компилируется для аналогичного
причина, потому что func (runner RunnerB)
не совпадает с func (runner Runner)
, и, следовательно, набор методов *Manager
не является надмножеством
интерфейс runnerRegisterer
.
Переходя к исходному вопросу:
Я занимаюсь написанием идиоматического кода Go и обнаружил, что интерфейсы
должны быть объявлены в пакетах, которые потребляют их, так как они
неявное.
Да, идея хорошая, но она не относится к вашей реализации так, как вы
думаю, что это так. Так как вы ожидаете иметь разные реализации
runnerRegisterer
и все они должны иметь метод с одинаковой подписью
используя интерфейс Runner
, имеет смысл определить Runner
в общем
место. Кроме того, как показано выше, Go не позволит вам использовать другой интерфейс
в подписи метода все равно.
Основываясь на моем понимании того, чего вы пытаетесь достичь, вот как я думаю
Вы должны изменить свой код:
- Определите
RunnerRegisterer
(примечание: это общедоступно) и Runner
в одном
пакет.
- Реализуйте ваш
RunnerCoach
в том же пакете и используйте выше
интерфейсы. Ваш RunnerCoach
использует типы, которые реализуют интерфейсы,
поэтому он определяет их.
- Реализуйте своих бегунов в другой пакет. Вы не определяете
Runner
интерфейс здесь.
- Реализуйте ваш
Manager
в другой пакет, который использует интерфейс
Runner
определен в пакете RunnerCoach
, потому что он должен принимать этот тип
в качестве аргумента, если он хочет быть использован как RunnerRegisterer
.