我正在尝试Go频道,并且遇到以下简单程序无法终止的问题。
基本上,我想发出一些异步HTTP get请求,然后wait,直到它们all完成。我正在使用缓冲通道,但不确定这是否是惯用方式。
func GetPrice(quotes chan string) {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://some/api", nil)
req.Header.Set("Accept", "application/json")
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
quotes <- string(body)
}
func main() {
const max = 3
quotes := make(chan string, max)
for i := 0; i < max; i++ {
go GetPrice(quotes)
}
for n := range quotes {
fmt.Printf("\n%s", n)
}
}
程序成功打印3个(最大)项目
{"price":"1.00"}
{"price":"2.00"}
{"price":"3.00"}
但随后将阻止并且永远不会退出。
[sync.WaitGroup
可以在这里用于等待所有goroutine,然后关闭quotes
通道:
func getPrice(quotes chan<- string, onExit func()) {
go func() {
defer onExit()
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://some/api", nil)
req.Header.Set("Accept", "application/json")
res, err := client.Do(req)
if err != nil {
panic(err) // should be handled properly
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
quotes <- string(body)
}()
}
func main() {
var wg sync.WaitGroup
const max = 3
quotes := make(chan string, max)
for i := 0; i < max; i++ {
wg.Add(1)
getPrice(quotes, func() { wg.Done() })
}
go func() {
defer close(quotes)
wg.Wait()
}()
for n := range quotes {
fmt.Printf("\n%s", n)
}
}
您可以执行的另一种方法:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func GetPrice(quotes chan string) {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://some/api", nil)
req.Header.Set("Accept", "application/json")
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
quotes <- string(body)
}
func run(quotes chan string, quit chan bool, max int) {
for num := range quotes {
fmt.Println(num)
max--
if max == 0 {
quit <- true
}
}
}
func main() {
const max = 3
quotes := make(chan string)
quit := make(chan bool)
go run(quotes, quit, max)
for i := 0; i < max; i++ {
go GetPrice(quotes)
}
<-quit
}
func GetPrice(quotes chan string) {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://some/api", nil)
req.Header.Set("Accept", "application/json")
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
quotes <- string(body)
}
func Consumer(chan string){
for n ,ok:= range quotes {
if !ok {
break
}
fmt.Printf("\n%s", n)
}
}
func main() {
const max = 3
quotes := make(chan string, max)
for i := 0; i < max; i++ {
go GetPrice(quotes)
}
go Consumer(quotes)
close(quotes)
}
希望对您有帮助。
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func GetPrice(quotes chan string, count int) {
for count > 0 {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://postman-echo.com/get?foo1=bar1&foo2=bar2", nil)
req.Header.Set("Accept", "application/json")
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
quotes <- string(body)
count--
}
close(quotes)
}
func main() {
const max = 3
ch := make(chan string)
go GetPrice(ch, max)
for num := range ch {
fmt.Println(num)
}
}