Senior
Úkol na Merge channel Implementujte funkci merge, která přijímá libovolný počet kanálů chan int a vrací jeden výstupní kanál, ze kterého lze číst všechny hodnoty z předaných kanálů. Předané kanály mimo funkci merge se po zápisu uzavřou. Po dokončení čtení z sloučeného kanálu by program měl vypisovat "ok". Funkce merge by měla trvat nejdéle 1 sekundu, zdrojové kanály se mohou nezavřít.
sobes.tech AI
Odpověď od AI
Для реализации функции merge в Go, которая принимает произвольное количество каналов chan int и возвращает один объединённый канал, из которого можно читать все значения, нужно использовать горутины и select. При этом важно, чтобы функция не зависала, если каналы-источники не закрываются, и чтобы после завершения чтения из объединённого канала программа вывела "ok".
Пример реализации с таймаутом 1 секунда, после которого merge завершится:
package main
import (
"fmt"
"time"
)
func merge(channels ...<-chan int) <-chan int {
out := make(chan int)
done := make(chan struct{})
// Запускаем горутину, которая читает из всех каналов
go func() {
defer close(out)
timer := time.NewTimer(time.Second)
defer timer.Stop()
for {
select {
case <-timer.C:
// Время вышло — завершаем
return
default:
active := false
for _, ch := range channels {
select {
case v, ok := <-ch:
if ok {
out <- v
timer.Reset(time.Second) // сбрасываем таймер при получении данных
active = true
}
default:
}
}
if !active {
// Нет данных во всех каналах, ждем немного
time.Sleep(10 * time.Millisecond)
}
}
}
}()
return out
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
defer close(ch1)
for i := 0; i < 5; i++ {
ch1 <- i
time.Sleep(100 * time.Millisecond)
}
}()
go func() {
defer close(ch2)
for i := 100; i < 105; i++ {
ch2 <- i
time.Sleep(150 * time.Millisecond)
}
}()
merged := merge(ch1, ch2)
for v := range merged {
fmt.Println(v)
}
fmt.Println("ok")
}
Важные моменты:
- Используем таймер 1 секунда, чтобы не зависать, если каналы не закрываются.
- При получении данных таймер сбрасывается.
- После окончания чтения из объединённого канала выводим "ok".
- Каналы-источники закрываются вне функции merge, как указано в условии.