Back to questions
МТС Cloud
Senior
4
// Задача 3 // Описать какую задачу решает данный код // Какие проблемы есть в этом решении? // Как бы вы переписали этот код? var c int type Trace struct { // Some fields here } type Sender interface { Send(Trace) } func Do(sender Sender, tr Trace) { c++ if c == 100 { sender.Send(tr) c = 0 } }
Companies where asked
Answer from AI
sobes.tech AI
Этот код решает задачу периодической отправки объекта Trace через интерфейс Sender после накопления 100 вызовов функции Do.
Проблемы в этом решении:
- Глобальная переменная c: Использование глобальной переменной для подсчёта вызовов не потокобезопасно и может привести к гонкам данных при параллельном вызове Do.
- Отсутствие синхронизации: Нет мьютексов или других механизмов защиты, что делает код небезопасным в многопоточной среде.
- Жёсткая логика: Отправка происходит ровно на 100-м вызове, нет гибкости для изменения порога или сброса счётчика.
- Отсутствие обработки ошибок: Метод Send не возвращает ошибку, и её невозможно обработать.
Как переписать:
- Инкапсулировать счётчик в структуру с мьютексом для потокобезопасности.
- Сделать порог отправки настраиваемым.
- Добавить обработку ошибок.
Пример переписанного кода:
type Trace struct {
// поля
}
type Sender interface {
Send(Trace) error
}
type SenderWithCounter struct {
sender Sender
count int
limit int
mu sync.Mutex
}
func NewSenderWithCounter(s Sender, limit int) *SenderWithCounter {
return &SenderWithCounter{sender: s, limit: limit}
}
func (swc *SenderWithCounter) Do(tr Trace) error {
swc.mu.Lock()
defer swc.mu.Unlock()
swc.count++
if swc.count >= swc.limit {
err := swc.sender.Send(tr)
if err != nil {
return err
}
swc.count = 0
}
return nil
}
Такой подход обеспечивает безопасность при параллельном использовании и гибкость настройки.