我对golang
还很陌生。所以,请把剑给我(如果可能的话)。
我试图通过学习这里的教程从web上获取数据
在问之前,我看了很多参考资料,比如:
还有几个,但我想不通。
以下是你不想去游乐场的代码(原因尚不为人所知):
// MakeRequest : Makes requests concurrently
func MakeRequest(url string, ch chan<- string, wg *sync.WaitGroup) {
start := time.Now()
resp, err := http.Get(url)
defer func() {
resp.Body.Close()
wg.Done()
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
if err != nil {
fmt.Println(err)
panic(err)
}
secs := time.Since(start).Seconds()
body, _ := ioutil.ReadAll(resp.Body)
ch <- fmt.Sprintf("%.2f elapsed with response length: %d %s", secs, len(body), url)
}
func main() {
var wg sync.WaitGroup
output := []string{
"https://www.facebook.com",
"",
}
start := time.Now()
ch := make(chan string)
for _, url := range output {
wg.Add(1)
go MakeRequest(url, ch, &wg)
}
for range output {
fmt.Println(<-ch)
}
fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}
我将代码修改为(假设)处理goroutine中的错误,如下所示(go-playground):
func MakeRequest(url string, ch chan<- string, wg *sync.WaitGroup) {
start := time.Now()
resp, err := http.Get(url)
if err == nil {
secs := time.Since(start).Seconds()
body, _ := ioutil.ReadAll(resp.Body)
ch <- fmt.Sprintf("%.2f elapsed with response length: %d %s", secs, len(body), url)
// fmt.Println(err)
// panic(err)
}
defer wg.Done()
}
回答后,我将代码更改为此,它成功地移除了chan
死锁,但是现在我需要在main
中处理此问题:
func MakeRequest(url string, ch chan<- string, wg *sync.WaitGroup) {
defer wg.Done()
start := time.Now()
resp, err := http.Get(url)
if err == nil {
secs := time.Since(start).Seconds()
body, _ := ioutil.ReadAll(resp.Body)
ch <- fmt.Sprintf("%.2f elapsed with response length: %d %s", secs, len(body), url)
// fmt.Println(err)
// panic(err)
}
// defer resp.Body.Close()
ch <- fmt.Sprintf("")
}
但现在我陷入了僵局。
感谢和问候。
Temporarya
(阿戈朗·努比)
您正确地使用了恢复。您有两个问题:
>
您错误地使用了panic。只有在出现编程错误时才应该惊慌。避免使用恐慌,除非你相信删除程序是对所发生的事情的合理反应。在这种情况下,我只会返回错误,而不是panic。
你在恐慌中惊慌失措。正在发生的情况是,您首先在panic(err)
执行panish操作。然后在defer函数中,在resp.body.close()
处进行panising。当http.get返回错误时,它返回一个nil响应。这意味着resp.body.close()
作用于一个nil值。
func MakeRequest(url string, ch chan<- string, wg *sync.WaitGroup) {
defer wg.Done()
start := time.Now()
resp, err := http.Get(url)
if err != nil {
//handle error without panicing
}
// there was no error, so resp.Body is guaranteed to exist.
defer resp.Body.Close()
...
操场
func main() {
var wg sync.WaitGroup
output := []string{
"https://www.facebook.com",
"",
}
start := time.Now()
ch := make(chan string)
for _, url := range output {
wg.Add(1)
go MakeRequest(url, ch, &wg)
}
go func() {
wg.Wait()
close(ch)
}()
for val := range ch {
fmt.Println(val)
}
fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}
如何从围棋套路中出现的恐慌中恢复过来。以下是游乐场的链接:https://play.golang.org/p/lkvkuxmhjhi
我目前正在考虑如何编写测试来检查给定的代码是否出现了恐慌?我知道Go使用来捕捉恐慌,但与Java代码不同的是,您不能真正指定在发生恐慌时应该跳过哪些代码或您有哪些代码。所以如果我有一个函数: 我真的不知道是否发生了恐慌,我们恢复了,或者函数是否根本没有恐慌。如何指定在没有恐慌的情况下跳过哪些代码,以及在出现恐慌的情况下执行哪些代码?我如何检查我们是否从恐慌中恢复过来?
我试图找到正确的方法来使用工人围棋例程产生的结果,同时在所有工作完成后优雅地退出结果循环。为了说明,我做了以下示例。我的真实世界案例与这个例子略有不同,因为我不知道每个工人围棋例程将返回多少“工作”,显然这些for循环执行固定数量的结果(5)。 我是goroutines和频道的新手,但以下是我所理解的基本租户; 只有发送者才能关闭频道 在通道上执行将继续,直到通道关闭 这个例子是死锁,因为范围循环
我有一些图像只包含数字和分号。 您可以在这里看到更多:https://imgur.com/a/54dsl6h 它们在我看来非常干净和简单,但Tesseract认为它们是空的“页面”()。 我怎么做才能让Tesseract更好地识别角色?
问题内容: 我想派生一个go进程并获取新进程的ID,但是我在或库中看到的只是启动一个新进程。 问题答案: 您应该从包装中获取。 请注意,这是在根本不使用任何线程的情况下发明的,并且一个进程中始终只有一个执行线程,因此分叉是安全的。使用Go,情况完全不同,因为它大量使用OS级线程来为其goroutine调度提供动力。 现在,在Linux上未经修饰的子进程将在所有活动线程中只有一个线程(在父进程中调用
问题内容: 我正在尝试将对象保存到数据库中,但是抛出错误。 问题出在表格内,用一个复选框表示。如果未选中该复选框,则显然不传递任何内容。这就是错误被排除的地方。 我如何正确处理并捕获此异常? 该行是 问题答案: 使用MultiValueDict的方法。这在标准字典中也存在,并且是一种在不存在默认值的情况下获取值的方法。 通常,