Senior
Tâche de fusion de canal Implémentez la fonction merge, qui prend un nombre arbitraire de canaux chan int et retourne un seul canal de sortie, à partir duquel on peut lire toutes les valeurs des canaux passés. Les canaux passés en dehors de la fonction merge sont fermés après l'écriture. Après avoir terminé la lecture du canal fusionné, le programme doit afficher "ok". La fonction merge ne doit pas prendre plus d'une seconde, les canaux sources peuvent ne pas se fermer.
sobes.tech IA
Réponse de l'IA
Для реализации функции 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, как указано в условии.