在链接的游乐场示例中,我定义了一个类型:
type DoMap map[int]func(Doer) string
我定义的接口类型中的Doer
。
我在具体类型MyDoer
上实现接口。我希望能够构造一个DoMap
,其中该映射中的条目包含以下两个函数:
func(Doer) string // this works
func(*MyDoer) string // this doesn't
func(MyDoer) string // more-or-less the same idea, also doesn't
我不能,虽然很明显它们是不同的类型,但我想知道为什么我不能,因为函数确保我必须提供MyDoer
来实现Doer
。
这还不足以确保我履行与该职能部门的合同吗?
还有另一种方法可以达到这个目的吗?
https://play.golang.org/p/sJ2Rg3neL7
有些评论的形式是“它们不同”“这是规范”但我可以将MyDoer
传递给接受Doer
的函数 - 如果接口已实现:为什么要放置它进入地图会改变结果吗?
有一个要求解释“真正的问题”以及为什么我不能只使用类型地图的问题。我会尽力而为:
DoMap
不能是类型的地图。我正在编写一个库,允许开发人员根据开发人员编写的接受开发人员定义类型(业务消息)的函数(业务逻辑)的输出,简洁地定义成功或失败的状态机。该库的存在是为了确保一系列转换可以序列化并记录在别处,然后由库的第三方用户进行验证。我最初并没有说出这一切,因为它忽略了这一点 - 没有一个简单的答案。
现在我觉得我因为不切实际的问题而烦恼所有人,因为我没有快速拨打Rob Pike,我可能会删除它,除非有人愿意相信我需要做什么我需要做,并提出建议。
答案 0 :(得分:1)
您没有概述具体问题(原因)。这使得很难建议替代方案,因为看起来你正试图在go中重新创建另一种语言。
按优先顺序,您可以按预期使用类型系统:
type DoMap map[int]func(Doer) string
type Doer interface {
Do() int
AlsoDo() int
}
https://play.golang.org/p/uPzoOZiLQG
或者你可以绕过类型系统:
type DoMap map[int]interface{}
https://play.golang.org/p/lfKPkwhOGa
但我不建议 - 更好地使用语言提供的工具,而不是试图使它们变形。
接口的目的是宣传一个关于函数的契约 - 它们需要它们的参数,而不是更多。但是你也想在参数上调用AlsoDo,所以如果你想这样做,就把它放在合同中。然后一切都会按照你的意愿运作。该函数的合同应该在函数旁边发布,如您的示例所示,它应该在您的控制之下。
[编辑] 最后,如果你不控制传入的类型,也许你应该重新思考你的地图的想法。它可能是一个map [int] Doer,Doer是一个接口(你应该控制它)。这使您可以在库中宣传您需要的内容,并且用户可以在其中放置他们想要的任何类型(以及他们想要的任何其他依赖项)。
// Library
type DoMap map[int]Doer
type Doer interface {
Do() int
}
// Client
type MyDoer struct {
myint int
}
func (d *MyDoer) Do() int {
fmt.Println(d.AlsoDo())
return d.myint + 1
}
func (d *MyDoer) AlsoDo() int {
return d.myint + 2
}
https://play.golang.org/p/cs01C8bSKo
[EDIT2]最后的编辑,如果建立一个fsm管理链,你可能会发现这个小项目鼓舞人心。它绝对应该没有太多麻烦,只是不像你第一次尝试任何类型的函数映射一样: