Конкурентный вывод уникальных элементов среза

Используйте атомарную проверку-и-добавление через sync.Map.LoadOrStore либо одну mutex-секцию для обычной map. Отдельные неблокированные чтения оставляют гонку.

Короткий ответ

Что ответить на собеседовании

Используйте атомарную проверку-и-добавление через sync.Map.LoadOrStore либо одну mutex-секцию для обычной map. Отдельные неблокированные чтения оставляют гонку.

Подробный разбор

Ответ с пояснениями

Условие

Дан срез целых чисел: values := []int{3, 3, 2, 1, 2, 1, 1, 2, 4}. Необходимо напечатать каждый различный элемент ровно один раз, используя несколько горутин. Порядок вывода не важен, главное – отсутствие повторов. В исходном примере происходит гонка данных при записи в обычную map, что приводит к некорректному результату. Нужно исправить код, обеспечив безопасный конкурентный доступ к общей структуре (например, через mutex или sync.Map).

func main() {
 values := []int{3, 3, 2, 1, 2, 1, 1, 2, 4}
 var idx map[int]struct{}

 for _, v := range values {
  go func() {
   if _, ok := idx[v]; ok {
    return
   }
   idx[v] = struct{}{}
   log.Println(v)
  }()
 }
}

Ответ

Используйте атомарную проверку-и-добавление через sync.Map.LoadOrStore либо одну mutex-секцию для обычной map. Отдельные неблокированные чтения оставляют гонку.

Краткий вариант, нужны sync и log:

values := []int{3, 3, 2, 1, 2, 1, 1, 2, 4}
var seen sync.Map
var wg sync.WaitGroup
for _, value := range values {
    wg.Add(1)
    go func(n int) {
        defer wg.Done()
        if _, loaded := seen.LoadOrStore(n, struct{}{}); !loaded {
            log.Println(n)
        }
    }(value)
}
wg.Wait()

Числа 1,2,3,4 выводятся каждое один раз, порядок произвольный. Передача аргумента исключает проблемы старой семантики цикла, WaitGroup не даёт main завершиться раньше печати.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее