Фатальная ошибка: все горутины спят - тупик! ошибка

Я новичок в параллелизме в 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

ваш потребитель запускается только один раз. Поместите его в цикл for

Burak Serdar 27.11.2022 19:50

Спасибо, это, кажется, пб

DvdiidI 28.11.2022 08:01
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
2
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш потребитель должен работать в цикле, об этом уже упоминалось.

Измените первый параметр потребителя так, чтобы он был 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 секунды.

Другие вопросы по теме