
[英]I wrote the rest api but body is return nil in golang . Why returning “0 {<nil> false [] <nil> false 0 <nil> 0}”
[英]why I push false to channel once, but select got false twice in golang?
我是golang的新手,正在研究golang的并发,并尝试写了一个简单的爬虫demo,当我读取所有给定的url时,我向processChannel
推送一个false
,这个推送只会执行一次; 然后在其他 goroutine 中,我在processChannel
上选择,当得到一个false
时,我关闭了申请通道,但是,在这个选择的情况下,我得到了两次 false,并且因为“恐慌:关闭关闭的通道”而感到恐慌所以,我不能明白为什么我推了一次false
,但选择了两次false
吗??? 所有代码如下:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
"time"
)
var applicationStatus bool
var urls []string
var urlsProcessed int
var foundUrls []string
var fullText string
var totalURLCount int
var wg sync.WaitGroup
var v1 int
func main() {
applicationStatus = true
statusChannel := make(chan int)
textChannel := make(chan string)
processChannel := make(chan bool)
totalURLCount = 0
urls = append(urls, "https://www.msn.cn/zh-cn/news/other/nasa%E7%AC%AC%E4%BA%94%E6%AC%A1%E8%A7%82%E5%AF%9F%E5%88%B0%E9%BB%91%E6%B4%9E%E5%90%83%E6%8E%89%E4%B8%80%E9%A2%97%E6%B5%81%E6%B5%AA%E7%9A%84%E6%81%92%E6%98%9F/ar-AA15ybhx?cvid=0eaf927e48604c0588413d393c788a8f&ocid=winp2fptaskbarent")
urls = append(urls, "https://www.msn.cn/zh-cn/news/other/nasa%E7%AC%AC%E4%BA%94%E6%AC%A1%E8%A7%82%E5%AF%9F%E5%88%B0%E9%BB%91%E6%B4%9E%E5%90%83%E6%8E%89%E4%B8%80%E9%A2%97%E6%B5%81%E6%B5%AA%E7%9A%84%E6%81%92%E6%98%9F/ar-AA15ybhx?cvid=0eaf927e48604c0588413d393c788a8f&ocid=winp2fptaskbarent")
fmt.Println("Starting spider")
urlsProcessed = 0
totalURLCount = len(urls)
go evaluateStatus(statusChannel, processChannel)
go readURLs(statusChannel, textChannel)
go appendToFullText(textChannel, processChannel)
for {
if applicationStatus == false {
fmt.Println(fullText)
fmt.Println("Done!")
break
}
//select {
//case sC := <-statusChannel:
// fmt.Println("Message on statusChannel", sC)
//}
}
}
func evaluateStatus(statusChannel chan int, processChannel chan bool) {
for {
select {
case status := <-statusChannel:
urlsProcessed++
if status == 0 {
fmt.Println("got url")
}
if status == 1 {
close(statusChannel)
}
if urlsProcessed == totalURLCount {
fmt.Println("=============>>>>urlsProcessed")
fmt.Println(urlsProcessed)
fmt.Println("read all top-level url")
processChannel <- false
applicationStatus = false
}
}
}
}
func readURLs(statusChannel chan int, textChannel chan string) {
time.Sleep(time.Millisecond * 1)
fmt.Println("grabing ", len(urls), " urls")
for _, url := range urls {
resp, _ := http.Get(url)
text, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("No HTML body")
}
textChannel <- string(text)
statusChannel <- 0
}
}
func appendToFullText(textChannel chan string, processChannel chan bool) {
for {
select {
case pC := <-processChannel:
fmt.Println("pc==============>>>")
fmt.Println(pC)
if pC == true {
// hang out
}
if pC == false {
// all url got
close(textChannel)
close(processChannel)
}
case tC := <-textChannel:
fmt.Println("text len: ")
fmt.Println(len(tC))
fullText += tC
}
}
}
感谢您的帮助。
关闭通道上的接收操作始终可以立即进行,在接收到任何先前发送的值后产生元素类型的零值。
这可以在下面的 ( playground ) 演示中看到(注释显示输出的内容):
func main() {
processChannel := make(chan bool)
go func() {
processChannel <- true
processChannel <- false
close(processChannel)
}()
fmt.Println(<-processChannel) // true
fmt.Println(<-processChannel) // false
fmt.Println(<-processChannel) // false
select {
case x := <-processChannel:
fmt.Println(x) // false
}
}
在您的代码中,您正在关闭processChannel
,因此未来的接收将返回默认值 ( false
)。 一种解决方案是在关闭后使用processChannel = nil
,因为:
一个 nil 通道永远不会准备好进行通信。
但是,在您的情况下, appendToFullText
在pC == false
时关闭两个通道; 因此,您可能应该在这样做之后return
(因为两个通道都关闭了,所以保持循环运行没有意义)。
请注意,我只扫描了您的代码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.