Опиши дизайн процессора с методом Process, принимающим событие с типом и пейлоадом в Go
Что проверяют
Как вы разложите задачу на интерфейсы и что сделаете с полиморфным пейлоадом. Это типовая заготовка обработчика событий, и по ней видно, пишете ли вы идиоматичный Go или переносите привычки из языка с наследованием.
Как отвечать
Начните с формы события. Тип держите отдельным полем, а пейлоад заранее не разбирайте:
type Event struct {
ID string
Type string
Payload json.RawMessage
}
type Handler interface {
Handle(ctx context.Context, e Event) error
}json.RawMessage откладывает разбор до обработчика, который знает нужную структуру, и процессору не приходится знать все схемы сразу.
Дальше сам процессор: не один разрастающийся switch, а реестр обработчиков по типу события.
func (p *Processor) Process(ctx context.Context, e Event) error {
h, ok := p.handlers[e.Type]
if !ok {
return fmt.Errorf("%w: %s", ErrUnknownType, e.Type)
}
return h.Handle(ctx, e)
}Что стоит проговорить вслух:
context.Contextпервым аргументом иerrorв возврате: без них нечем отменять работу и не на чем строить повторы;- неизвестный тип это ошибка с собственным значением, а не тихий пропуск: вызывающий сам решит, отбросить событие или отправить в очередь разбора;
- карта обработчиков заполняется при старте и дальше только читается, иначе нужен
sync.RWMutex; - дженерики убирают приведение типов из обработчиков: адаптер разбирает
Payloadв нужный тип и вызывает типизированную функцию.
Где спотыкаются
Пишут payload.(string) без второго возвращаемого значения. На чужих данных это паника, которая роняет процесс целиком, а не одно событие. Приведение типа всегда в форме с ok.
Второе: Process без контекста и без ошибки. Отменить нечего, отличить успешную обработку от неизвестного типа нечем, и повторная доставка событий строится на догадках.
Третье: запускают go h.Handle(...) прямо внутри Process ради скорости. Ошибка теряется, число горутин ничем не ограничено, порядок событий по одному ключу ломается. Параллельность живёт снаружи: пул воркеров, ограничитель, ожидание завершения.