2 回答
TA贡献1773条经验 获得超3个赞
IIUC,你的问题不是关于包,而是归结为一个函数(或方法)是否可以类型转换为另一个函数,该函数接受具有等效但不同接口类型的参数。
像这样的东西:
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 {})
答案似乎是否定的,因为 Go 不认为func (I1)
等同于func (interface{})
. Go规范是这样说的
函数类型表示具有相同参数和结果类型的所有函数的集合。
类型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
TA贡献1856条经验 获得超11个赞
解决方案
您有一个类型在两个包 A 和 B 中使用。包 A 导入包 B。
你必须避免循环依赖,所以你有三个选择:
在包 B 中定义类型,因此它在两个包中都可用。
在包 C 中定义类型,让 A 和 B 都导入包 C。
更改您的设计,使 A 和 B 中都不使用该类型。
无论该类型是接口还是任何其他类型,这些都是您的选择。
选择最适合您的设计目标的选项。
规则/成语
我正在练习编写惯用的 Go 代码,发现接口应该在使用它们的包中声明,因为它们是隐式的。
我有了冲动/想法——问题是它不太实用。如果接口只能在定义它们的包中使用,那么它们的用处就会小一些。标准库中充满了违反这条公理的代码。因此,我不认为所提出的规则——适用于所有情况、设计和上下文中的所有界面——是惯用的。
例如,查看bytes包。 func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error)
consumes io.Reader
,在另一个包中定义的接口。 func (r *Reader) WriteTo(w io.Writer) (n int64, err error)
consumes io.Writer
,在另一个包中定义的接口。
- 2 回答
- 0 关注
- 91 浏览
添加回答
举报