go - 结构类型作为映射键
问题描述
我们有以下功能:
func (h *Handler) Handle(message interface{}) error {
//here there is a switch for different messages
switch m := message.(type) {
}
}
此签名已给出且无法更改。处理程序处理大约 20 种不同的消息类型。
现在,其中一些消息(大约 4 条)需要特殊的后处理。在不同的包装中。
因此,我想这样做:
func (h *Handler) Handle(message interface{}) error {
//here there is a switch for different messages
switch m := message.(type) {
}
//only post-process if original message processing succeeds
postProcessorPkg.Process(message)
}
现在,在Process
函数中,我想快速查找消息类型是否确实是我们需要后处理的类型。我不想在switch
这里再做一次。有许多处理程序,在不同的包中,具有不同数量的消息类型,它应该是通用的。
所以我想在后处理器中注册消息类型,然后进行查找:
func (p *Postprocessor) Register(msgtype interface{}) {
registeredTypes[msgtype] = msgtype
}
接着
func (p *Postprocessor) Process(msgtype interface{}) error {
if ok := registeredTypes[msgtype]; !ok {
return errors.New("Unsupported message type")
}
prop := GetProp(registeredTypes[msgtype])
doSmthWithProp(prop)
}
现在这一切都行不通了,因为据我所知,我只能“注册”消息的实例,而不是消息类型本身。因此,地图只会匹配消息的特定实例,而不是它的类型,这正是我所需要的。
所以我想这需要重新设计。我可以完全放弃注册和地图查找,但是
- 我无法将
Handle
函数更改为特定类型(需要保留签名message interface{}
- 我想避免不得不使用
reflect
,因为我将很难与一些同事捍卫这样的解决方案。
解决方案
由于无法将类型设置为映射键,因此我最终决定实现以下解决方案,该解决方案基于 @Chrono Kitsune 的解决方案:
type Postprocess interface {
NeedsPostprocess() bool
}
type MsgWithPostProcess struct {}
func (p *MsgWithPostProcess) NeedsPostprocess() bool {
return true
}
type Msg1 struct {
MsgWithPostProcess
//other stuff
}
type Msg2 struct {
MsgWithPostProcess
//other stuff
}
type Msg3 struct {
//no postprocessing needed
}
func (p *Postprocessor) Process(msgtype interface{}) error {
if _, ok := msgtype.(Postprocess); ok {
//do postprocessing
}
}
在我的简单测试中,我只做了Msg1
并且Msg2
将被后处理,但不是Msg3
,这正是我想要的。
推荐阅读
- python - python sdist 中应该包含哪些文件?
- java - 对正则表达式感到困惑?如何阅读正则表达式
- web-services - Web 服务 Eclipse
- python - 如何使用OpenGL和Python通过(XYZ)坐标绘制折线
- java - 为每个用户更改一个变量
- python - 多个 GUI 来回通信
- google-cloud-dataflow - 谷歌数据流 GroupByKey 可以处理热键吗?
- matlab - 绘制电荷函数
- php - 尝试将特定的 PHP 表单值发布到 SOAP wsdl 但没有成功
- selenium - 如何使用官方的 selenium docker 镜像?