Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何为服务器和事件句柄设计具有单独包的事件驱动API?_Go - Fatal编程技术网

Go 如何为服务器和事件句柄设计具有单独包的事件驱动API?

Go 如何为服务器和事件句柄设计具有单独包的事件驱动API?,go,Go,背景 我有一个servercore包,其中包括server结构和用于从客户端发送/接收消息的所有核心逻辑 服务器将以不同的风格运行-例如欧盟、美国、澳大利亚。每种风格都有自己的一组不同的方法,客户机可以调用这些方法 我想创建单独的包,其中包括(仅)这些方法。例如,euhandles包装 问题 在某些情况下,这些方法必须依赖于在servercore包中实现的原始server方法 如何在golang设计出优雅的风格 潜在解决方案 (1)只需将这些方法移动到单独的包中-不起作用 Server.Regi

背景

我有一个servercore包,其中包括server结构和用于从客户端发送/接收消息的所有核心逻辑

服务器将以不同的风格运行-例如欧盟、美国、澳大利亚。每种风格都有自己的一组不同的方法,客户机可以调用这些方法

我想创建单独的包,其中包括(仅)这些方法。例如,euhandles包装

问题

在某些情况下,这些方法必须依赖于在servercore包中实现的原始server方法

如何在golang设计出优雅的风格

潜在解决方案

(1)只需将这些方法移动到单独的包中-不起作用

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软件包中的流行性等)?一旦您至少运行了一个框架实现,您就可以判断实用性。如果它有效,它是正确的。我不能谈论受欢迎程度。我建议你选一个看起来合理的,看看它是如何发展的。在这个方向上,你可能想考虑拥有一个服务器工厂。