fab*_*ous 5 types interface go go-map
我们有以下功能:
func (h *Handler) Handle(message interface{}) error {
//here there is a switch for different messages
switch m := message.(type) {
}
}
Run Code Online (Sandbox Code Playgroud)
此签名已提供且无法更改。处理程序处理大约 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)
}
Run Code Online (Sandbox Code Playgroud)
现在,在Process函数中,我想快速查找消息类型是否确实是我们需要后处理的类型。我不想在switch这里再做一次。有许多处理程序,在不同的包中,具有不同数量的消息类型,并且应该是通用的。
所以我想在后处理器中注册消息类型,然后进行查找:
func (p *Postprocessor) Register(msgtype interface{}) {
registeredTypes[msgtype] = msgtype
}
Run Code Online (Sandbox Code Playgroud)
进而
func (p *Postprocessor) Process(msgtype interface{}) error {
if ok := registeredTypes[msgtype]; !ok {
return errors.New("Unsupported message type")
}
prop := GetProp(registeredTypes[msgtype])
doSmthWithProp(prop)
}
Run Code Online (Sandbox Code Playgroud)
现在这一切都不起作用,因为据我所知,我只能“注册”消息的实例,而不是消息类型本身。因此,地图只会匹配消息的特定实例,而不是它的类型,而这正是我所需要的。
所以我想这需要重新设计。我可以完全放弃注册和地图查找,但是
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
}
}
Run Code Online (Sandbox Code Playgroud)
在我的简单测试中,我只对Msg1和进行Msg2了后处理,但不进行后处理Msg3,这正是我想要的。