英文:
how to correctly limit number of goroutines
问题
我正在为您翻译以下内容:
我正在从标准输入中获取URL行,例如:
$ echo -e 'https://golang.org\nhttps://godoc.org\nhttps://golang.org' | go run 1.go .
任务是从每个网页中获取单词"Go"的数量。但是我不允许启动超过5个goroutine,并且只能使用标准库。
以下是我的代码:
package main
import (
  "fmt"
  "net/http"
  "bufio"
  "os"
  "regexp"
  "io/ioutil"
  "time"
)
func worker(id int, jobs<-chan string, results chan<-int) {
  t0 := time.Now()
  for url := range jobs {
    resp, err := http.Get(url)
    if err != nil {
      fmt.Println("打开URL时出现问题", url)
      results<-0
      //continue
    }
    defer resp.Body.Close()
    html, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      continue
    }
    regExp:= regexp.MustCompile("Go")
    matches := regExp.FindAllStringIndex(string(html), -1)
    t1 := time.Now()
    fmt.Println("URL", url, "中的数量:", len(matches), "耗时:", 
t1.Sub(t0),  "工作ID:", id)
    results<-len(matches)
  }
}
func main(){
  scanner := bufio.NewScanner(os.Stdin)
  jobs := make(chan string, 100)
  results := make(chan int, 100)
  t0 := time.Now()
  for w:= 0; w<5; w++{
    go worker(w, jobs, results)
  }
  var tasks int = 0
  res := 0
  for scanner.Scan() {
      jobs <- scanner.Text()
      tasks ++
  }
  close(jobs)
  for a := 1; a <= tasks; a++ {
    res += <-results
  }
  close(results)
  t2 := time.Now()
  fmt.Println("总计:",res, "总耗时:", t2.Sub(t0) );
}
我认为它可以工作,直到我将超过5个URL(其中一个是不正确的)传递给标准输入。输出结果是:
 goroutine 9 [running]:
panic ...
显然,额外的goroutine已经启动。如何修复它?也许有更方便的方法来限制goroutine的数量?
英文:
I'm getting in 'stdin' lines of URL's like:
$ echo -e 'https://golang.org\nhttps://godoc.org\nhttps://golang.org' | go run 1.go .
The task is to get from each WEB-page number of word "Go". But I'm not allowed to start more than 5 goroutines and can use only standard library
Here is my code:
    package main
import (
"fmt"
"net/http"
"bufio"
"os"
"regexp"
"io/ioutil"
"time"
)
func worker(id int, jobs<-chan string, results chan<-int) {
t0 := time.Now()
for url := range jobs {
resp, err := http.Get(url)
if err != nil {
fmt.Println("problem while opening url", url)
results<-0
//continue
}
defer resp.Body.Close()
html, err := ioutil.ReadAll(resp.Body)
if err != nil {
continue
}
regExp:= regexp.MustCompile("Go")
matches := regExp.FindAllStringIndex(string(html), -1)
t1 := time.Now()
fmt.Println("Count for", url, ":", len(matches), "Elapsed time:", 
t1.Sub(t0),  "works id", id)
results<-len(matches)
}
}
func main(){
scanner := bufio.NewScanner(os.Stdin)
jobs := make(chan string, 100)
results := make(chan int, 100)
t0 := time.Now()
for w:= 0; w<5; w++{
go worker(w, jobs, results)
}
var tasks int = 0
res := 0
for scanner.Scan() {
jobs <- scanner.Text()
tasks ++
}
close(jobs)
for a := 1; a <= tasks; a++ {
res+=<-results
}
close(results)
t2 := time.Now()
fmt.Println("Total:",res, "Elapsed total time:", t2.Sub(t0) );
}
I thought it works until I passed more than 5 URL (one of them was incorrect) to stdin. The output was:
 goroutine 9 [running]:
panic ...
Obviously, extra goroutnes have been started. How to fix it? May be there are more convenient way to limit number of goroutines?
答案1
得分: 1
你的代码中只启动了5个goroutine。如果你真的想知道有多少个goroutine在运行,可以使用runtime.NumGoroutine函数。一些goroutine是由运行时启动的,还有一些是由网络获取数据时启动的。
英文:
> goroutine 9 [running]:
Some goroutines are started by the runtime, and by web fetches.
Looking at your code, you only started 5 goroutines.
If you really want to know how many go routines you are running use runtime.Numgoroutine
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论