在链接的操场示例中,我定义了一个类型:
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
的函数-如果实现了接口:为什么将其放入 map 会改变结果?更新2
有一个要求解释“真正的问题”,以及一个为什么我不能只使用类型映射的问题。我会尽力:
DoMap
不能是类型映射。我正在编写一个库,该库允许开发人员根据接受开发人员定义的类型(业务消息)的开发人员编写的函数(业务逻辑)的输出,简洁地定义成功或失败转换的状态机。该库的存在是为了确保可以将过渡系列序列化并记录到其他地方,并随后由库的第三方用户进行验证。我最初并不是说所有这些,因为它没有讲到重点-没有一个简单的答案。现在,我感觉到我每个急切的问题都困扰着我,并且由于我在快速拨号上没有Rob Pike,所以我可能会删除它,除非有人愿意相信我需要做我想做的事情做,并提出一些建议。
最佳答案
您尚未概述具体问题(原因)。这使得很难提出替代方案,因为您似乎正在尝试重新创建另一种语言。
按照优先顺序,可以按预期使用类型系统:
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 的概念。可能是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管理链,您可能会发现这个小项目很有启发性。它绝对应该毫无问题地可行,只是不完全与您第一次尝试使用任何类型的函数映射完全不一样:
https://github.com/ryanfaerman/fsm