Go 如何为服务器和事件句柄设计具有单独包的事件驱动API?
背景 我有一个servercore包,其中包括server结构和用于从客户端发送/接收消息的所有核心逻辑 服务器将以不同的风格运行-例如欧盟、美国、澳大利亚。每种风格都有自己的一组不同的方法,客户机可以调用这些方法 我想创建单独的包,其中包括(仅)这些方法。例如,euhandles包装 问题 在某些情况下,这些方法必须依赖于在servercore包中实现的原始server方法 如何在golang设计出优雅的风格 潜在解决方案 (1)只需将这些方法移动到单独的包中-不起作用Go 如何为服务器和事件句柄设计具有单独包的事件驱动API?,go,Go,背景 我有一个servercore包,其中包括server结构和用于从客户端发送/接收消息的所有核心逻辑 服务器将以不同的风格运行-例如欧盟、美国、澳大利亚。每种风格都有自己的一组不同的方法,客户机可以调用这些方法 我想创建单独的包,其中包括(仅)这些方法。例如,euhandles包装 问题 在某些情况下,这些方法必须依赖于在servercore包中实现的原始server方法 如何在golang设计出优雅的风格 潜在解决方案 (1)只需将这些方法移动到单独的包中-不起作用 Server.Regi
Server.RegisterHandle("someEventName",euhandles.methodFromEu)
包euhandles无法在servercore.Server结构上创建方法。这在Go中是禁止的(无法在第三方结构上创建方法)
(2)在单独的包中定义函数,然后简单地“注册”它们-不起作用
Server.RegisterHandle("someEventName",euhandles.methodFromEu)
问题-methodFromEu函数将无法访问任何服务器方法
(3)使用嵌入:
type serverEU struct { server *servercore.Server }
func (s *serverEU) HandleThat {}
s := new(serverEU)
s.server.registerHandle("someEventName", s.HandleThat)
问题-它变得有点麻烦(添加额外的层只是为了实现一些句柄/方法),看起来不“干净”
(4)依赖项注入
我在发布问题后不久就想到了这一点,为了全面起见,我补充说:
# in euhandles:
func HandleThat(s *server)
# elsewhere:
s.registerHandle("someEventName", euhandles.HandleThat)
# in servercore:
func (s *server) registerHandle(name string, handleFunc func(*server)) {
s.handles[name]=func(s *server) { handleFunc(s)}
}
不确定Go程序员认为这有多好/合适
有什么惯用的、干净的方法将事件/句柄与核心服务器分离吗?我要做的第一件事是使用嵌入,尽管没有额外的间接操作:
type ServerEU struct {
*servercore.Server
}
s := ServerEU{Server:&baseServer}
s.registerHandle("someEventName", s.HandleThat)
您可以尝试的另一件事是服务器中的函数指针:
type Server struct {
// stuff
LocaleSpecificFunc func(args)
}
在包装中:
func NewUEServer() *Server {
s:=Server{//initializers}
s.LocaleSpecificFunc=func(args) {
// Here, LocaleSpecificFunc implementation can use s
}
return &s
}
如果您必须在某个时候将
HandleThat
传递给registerHandle()
,则HandleThat
不是服务器不可分割的一部分。因此,您的DI选项(4)比实际嵌入更有意义。谢谢,这很有帮助。与我刚才添加的(4)注入相比,您对建议选项有什么偏好(实用性/正确性/在最常用的go软件包中的流行性等)?一旦您至少运行了一个框架实现,您就可以判断实用性。如果它有效,它是正确的。我不能谈论受欢迎程度。我建议你选一个看起来合理的,看看它是如何发展的。在这个方向上,你可能想考虑拥有一个服务器工厂。