Как разработать управляемый событиями API с отдельными пакетами для сервера и обработчиков событий? - PullRequest
0 голосов
/ 06 января 2020

Фон

У меня есть пакет servercore , который включает server struct и все основные логи c для отправки / получения сообщений от клиенты.

Сервер будет работать с различными вариантами - например, ЕС, США, AUS. Каждый вариант имеет свой собственный набор отдельных методов, которые могут вызывать клиенты.

Я хотел бы создать отдельные пакеты, которые включают (только) эти методы. Например, упаковка euhandles .

Проблема

Эти методы в некоторых случаях должны опираться на оригинальные методы server , реализованные в servercore пакет.

Как это может быть элегантно спроектировано в golang?

Потенциальные решения

(1) просто двигаться методы в отдельный пакет - не работают

euhandles пакета не могут создавать методы на servercore.Server struct. Это запрещено в 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 -программистов.

Существует ли какой-либо идиоматизм c, чистый способ отделения событий / дескрипторов от главного сервера?

Ответы [ 2 ]

0 голосов
/ 06 января 2020

Если в какой-то момент вам нужно передать HandleThat в registerHandle(), HandleThat не является неотъемлемой частью сервера. Так что ваша опция DI (4) имеет больше смысла, чем встраивание на самом деле.

0 голосов
/ 06 января 2020

Первое, что я хотел бы сделать, это использовать встраивание, но без дополнительного косвенного обращения:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...