Goroutines 在执行后卡住了

Goroutines stuck after execution

我想要有限数量的 goroutine 来进行一些计算(func worker(),它进行一些计算并将结果放在一个通道中)。还有另一个频道,为我的工人提供“工作”。结果我可以看到所有作业都已正确计算,但在计算执行后卡住了。

package main
import (
    "bufio"
    "fmt"
    "os"
    "net/http"
    "io/ioutil"
    "strings"
    "time"
)


func worker(id int, urls <- chan string, results chan<- int) {
    var data string
    for url := range urls {
        fmt.Println("worker", id, "started  job", url)
        if (strings.HasPrefix(url, "http") ||  strings.HasPrefix(url, "https")) {
            resp, err := http.Get(url)
            if err != nil {
                fmt.Println(err)
            }
            defer  resp.Body.Close()
            body, err := ioutil.ReadAll(resp.Body)
            if err != nil {
                fmt.Println(err)
            }
            data = string(body)
        } else {
            body, err := ioutil.ReadFile(url)
            if err != nil {
                fmt.Println(err)
            }
            data = string(body)
        }
        number := strings.Count(data, "Go")
        fmt.Println("worker", id, "finished  job", url, "Number of Go is", number)
        results <- number
    }
    return
}

func main() {
    final_result := 0
    maxNbConcurrentGoroutines := 5
    numJobs := 0
    urls := make(chan string)
    results := make(chan int)

    scanner := bufio.NewScanner(os.Stdin)
    start := time.Now()
    for w := 1; w <= maxNbConcurrentGoroutines; w++ {
        go worker(w, urls, results)
    }
    for scanner.Scan() {
        url := (scanner.Text())
        urls <- url
        numJobs += 1
    }
    close(urls)
    for num := range results {
        final_result += num
    }
    t := time.Now()
    elapsed := t.Sub(start)
    for i := 1; i <= numJobs; i++ {
        one_result := <- results
        final_result += one_result
    }
    fmt.Println("Number = ", final_result)
    fmt.Println("Time = ", elapsed)
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "error:", err)
        os.Exit(1)
    }
}

我尝试使用 https://gobyexample.com/worker-pools 从结果通道中提取所有值,但没有成功。我应该怎么做才能将它拆开并走得更远。以下是如何 运行 的示例:

echo -e 'https://golang.org\n/etc/passwd\nhttps://golang.org\nhttps://golang.org' | go run 1.go

您的程序没有 return 因为它等待结果通道的关闭状态。

https://gobyexample.com/worker-pools中获取结果的循环不同:

for a := 1; a <= numJobs; a++ {
    <-results
}

如果您想使用 for num := range results,您需要 close(results) 并确定何时调用它。

您可以在 https://gobyexample.com/waitgroups

查看另一个使用 WaitGroup 的示例