#api #rest #go #multi-tenant
#API #rest #Вперед #многопользовательский
Вопрос:
У меня есть сервер API, написанный на Go, который выполняет некоторую работу для разных клиентов. У меня есть много конечных точек, которые должны реализовывать различный код на основе клиента, который его вызывает, так, например:
s.GET("/api/orders", a.getOrders)
вызовет a.getOrders
обработчик, который после своей работы вернет одинаковую структуру JSON для всех клиентов, но реализация для получения данных может отличаться (иногда для клиента мне нужно вызвать другой веб-сервис, для другого мне нужно запросить разные таблицы БД и т.д.). Я думаю создать разные пакеты для каждого клиента, поэтому у меня будет common
(для общих реализаций), tenanta
(для конкретных реализаций tenant A), tenantb
, tenantc
и так далее… Теперь мой вопрос: какой наилучший способ обработать «перенаправление»? Первая (и, вероятно, плохая) вещь, о которой я могу подумать, это поместить переключатель в мой a.getOrders
обработчик и проанализировать tenantID
из сеанса или URL:
switch tenantID {
case "tenanta":
tenanta.getOrders()
case "tenantb":
tenantb.getOrders()
case "tenantc":
tenantc.getOrders()
default:
common.getOrders()
}
Очевидно, что это могло бы стать длинным довольно быстро (на данный момент мне пришлось бы обрабатывать более 20 клиентов).
Есть ли лучший способ справиться с этой ситуацией?
Спасибо
Комментарии:
1. Карта арендаторов?
Ответ №1:
Вы можете создать интерфейс клиента примерно так
type tenant interface{
getOrders() Orders
}
Теперь вы можете объявить любое количество клиентов, реализующих этот интерфейс
package main
import (
"fmt"
)
type tenant interface {
getOrders()
}
type TenantA struct {
}
func (t TenantA) getOrders() {
fmt.Println("Tenant A")
}
var tenantMap = map[string]tenant{
"T-A": TenantA{},
}
func main() {
fmt.Println("Hello")
teneantTest := "T-A"
curTeneant, ok := tenantMap[teneantTest]
if !ok {
fmt.Println("Not Found")
return
}
curTeneant.getOrders()
}
Теперь все ваши клиенты используют один и тот же интерфейс, и это можно будет проверить во время компиляции, если у всех клиентов также определен минимальный набор функций
Это также приведет к более чистой абстракции
Комментарии:
1. Большое вам спасибо, это означает, что если только один из клиентов реализует свой собственный код, я должен определить пустые функции для всех остальных клиентов?
2. Нет, вы не должны добавлять эту функцию в интерфейс, интерфейс должен иметь то, что является общим для всех, также примите ответ, если это поможет 😊