Я новичок в параллелизме в Go, поэтому я попробовал пример с каналами и горутинами. Я хочу иметь модель производитель-потребитель. Функция-производитель постоянно выдает случайные строки, а потребитель модифицирует их, переводя их в верхний регистр. Я хочу запустить его в течение ограниченного времени (2 секунды).
package main
import (
"fmt"
"math/rand"
"strings"
"time"
)
func producer(x []string, c chan string) {
i := 1
for i > 0 {
randomIndex := rand.Intn(len(x))
pick := x[randomIndex]
c <- pick
}
}
func consumer(x string, c chan string) {
x1 := strings.ToUpper(x)
c <- x1
}
func main() {
s := []string{"one", "two", "three", "four"}
c1 := make(chan string)
d1 := make(chan string)
go producer(s, c1)
go consumer(<-c1, d1)
stop := time.After(2000 * time.Millisecond)
for {
select {
case <-stop:
fmt.Println("STOP AFTER 2 SEC!")
return
default:
fmt.Println(<-d1)
time.Sleep(50 * time.Millisecond)
}
}
}
Я получаю только один элемент массива и некоторые ошибки. Какие изменения нужно внести, чтобы этот пример заработал?
ВЫХОД:
ДВА
фатальная ошибка: все горутины спят - тупик!
горутина 1 [чан получить]: основной.главный()
горутина 6 [отправить чан]: main.producer({0xc00004e040, 0x4, 0x0?}, 0x0?) созданный основным. основной статус выхода 2
Спасибо, это, кажется, пб
Ваш потребитель должен работать в цикле, об этом уже упоминалось.
Измените первый параметр потребителя так, чтобы он был chan string
вместо строки. Таким образом, производитель может постоянно писать в этот канал, чтобы потребитель мог публиковать на другом канале, пока не истечет срок.
func consumer(consumeChan chan string, outCh chan string) {
for {
select {
case s := <- consumeChan:
s = strings.ToUpper(s)
outCh <- s
}
}
}
Прямо сейчас в основной функции перед вызовом go consumer()
вы ждете первого ответа на канал c1
от производителя. Вместо этого передайте канал c1
в качестве первого параметра.
func main() {
s := []string{"one", "two", "three", "four"}
c1 := make(chan string)
d1 := make(chan string)
go producer(s, c1)
go consumer(c1, d1)
stop := time.After(2000 * time.Millisecond)
for {
select {
case <-stop:
fmt.Println("STOP AFTER 2 SEC!")
return
case response := <- d1:
fmt.Println(response)
time.Sleep(50 * time.Millisecond)
}
}
}
Это должно показать вам непрерывную запись случайных чисел производителем на канал c1
и непрерывную запись потребителем на канал d1 с текстом в верхнем регистре, пока не истекут 2 секунды.
ваш потребитель запускается только один раз. Поместите его в цикл for