Sobes.tech
Назад к вопросам
Senior
3

// Задача 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 } }

Компании, где спрашивали
МТС CloudМТС Cloud

Ответ от нейросети

sobes.tech AI

Этот код решает задачу периодической отправки объекта Trace через интерфейс Sender после накопления 100 вызовов функции Do.

Проблемы в этом решении:

  1. Глобальная переменная c: Использование глобальной переменной для подсчёта вызовов не потокобезопасно и может привести к гонкам данных при параллельном вызове Do.
  2. Отсутствие синхронизации: Нет мьютексов или других механизмов защиты, что делает код небезопасным в многопоточной среде.
  3. Жёсткая логика: Отправка происходит ровно на 100-м вызове, нет гибкости для изменения порога или сброса счётчика.
  4. Отсутствие обработки ошибок: Метод 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
}

Такой подход обеспечивает безопасность при параллельном использовании и гибкость настройки.