Live coding: задачи на Go — конкурентные запросы, замыкания в горутинах, фильтрация дубликатов, счётчик с потокобезопасностью, буферизированные каналы, таймаут функции
Ответ от нейросети
sobes.tech AI
В Go часто требуется писать конкурентный код с горутинами и каналами. Рассмотрим ключевые моменты:
-
Конкурентные запросы — можно запускать несколько горутин, каждая выполняет запрос, результаты собираются через канал.
-
Замыкания в горутинах — важно правильно захватывать переменные цикла, чтобы избежать ошибок с общим состоянием.
-
Фильтрация дубликатов — можно использовать map для отслеживания уже встреченных значений.
-
Счётчик с потокобезопасностью — применяют sync.Mutex или atomic операции.
-
Буферизированные каналы — позволяют отправлять несколько значений без блокировки отправителя.
-
Таймаут функции — реализуется через select с time.After.
Пример, который объединяет несколько из этих аспектов:
package main
import (
"fmt"
"sync"
"time"
"math/rand"
)
func main() {
// Буферизированный канал для результатов
results := make(chan int, 5)
var wg sync.WaitGroup
// Потокобезопасный счётчик
var mu sync.Mutex
counter := 0
// Множество для фильтрации дубликатов
seen := make(map[int]bool)
// Запускаем 5 конкурентных горутин
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
// Замыкание с копией id
time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)
value := id * 10
// Отправляем результат в канал с таймаутом
select {
case results <- value:
// Увеличиваем счётчик потокобезопасно
mu.Lock()
counter++
mu.Unlock()
case <-time.After(300 * time.Millisecond):
fmt.Printf("Горутина %d: таймаут при отправке\n", id)
}
}(i)
}
// Закрываем канал после завершения всех горутин
go func() {
wg.Wait()
close(results)
}()
// Читаем из канала и фильтруем дубликаты
for val := range results {
if !seen[val] {
fmt.Println("Получено уникальное значение:", val)
seen[val] = true
} else {
fmt.Println("Дубликат пропущен:", val)
}
}
fmt.Println("Всего уникальных значений отправлено:", counter)
}
В этом примере показано:
- Запуск конкурентных горутин с замыканием (копия id в параметре функции).
- Использование буферизированного канала для сбора результатов.
- Таймаут при отправке в канал.
- Потокобезопасное увеличение счётчика.
- Фильтрация дубликатов при чтении из канала.
Такой подход часто используется для параллельной обработки и сбора результатов с контролем времени и безопасности.