Войти Регистрация
Конкурентность

3. Переводы в Go: мьютекс в счёте

Сложная

Go · 43 строк

Сервис держит счета клиентов в памяти: карта заполняется при старте и дальше только читается. Transfer и Balance вызываются из горутин gRPC-сервера.

Отметьте строки с ошибками.

В работе: Быстрый контур переводов между своими счетами в мобильном банке.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Плюс 1 вопрос про поведение программы — на зачёт не влияют. Ответ один на подход: после него показываем разбор.
sync.Mutexкопирование мьютексадедлокdefer

Источник: на задачах Альфа-Банка: переводы между счетами. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. package payments
  2. import (
  3. "errors"
  4. "sync"
  5. )
  6. var ErrNoMoney = errors.New("недостаточно средств")
  7. type Account struct {
  8. mu sync.Mutex
  9. ID string
  10. Balance int64 // копейки
  11. }
  12. // Available показывает остаток в мобильном приложении.
  13. func (a Account) Available() int64 {
  14. a.mu.Lock()
  15. defer a.mu.Unlock()
  16. return a.Balance
  17. }
  18. type Bank struct {
  19. accounts map[string]*Account // заполняется при старте, дальше только читается
  20. }
  21. func (b *Bank) Balance(id string) int64 {
  22. return b.accounts[id].Available()
  23. }
  24. func (b *Bank) Transfer(fromID, toID string, amount int64) error {
  25. from, to := b.accounts[fromID], b.accounts[toID]
  26. from.mu.Lock()
  27. to.mu.Lock()
  28. if from.Balance < amount {
  29. return ErrNoMoney
  30. }
  31. from.Balance -= amount
  32. to.Balance += amount
  33. to.mu.Unlock()
  34. from.mu.Unlock()
  35. return nil
  36. }