首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用sync.WaitGroup panics完成的WebCrawl练习。我做错了什么?Go惯用解决方案是什么?

在使用sync.WaitGroup进行并发编程时,panic通常是由于以下几个原因造成的:

  1. 未正确初始化WaitGroup:确保在使用WaitGroup之前已经调用了Add方法来设置计数器。
  2. 忘记调用Done方法:每个启动的goroutine在完成工作后都应该调用Done方法来减少计数器。
  3. 在WaitGroup计数器归零之前访问共享资源:这可能导致竞态条件,从而引发panic
  4. 在WaitGroup上执行阻塞操作:例如,在Wait方法调用之后,不应该再有其他可能阻塞的操作,否则可能会导致死锁。

Go惯用解决方案

以下是一个使用sync.WaitGroup进行WebCrawl的示例代码,展示了如何正确使用WaitGroup以避免panic

代码语言:txt
复制
package main

import (
    "fmt"
    "net/http"
    "sync"
)

func crawl(url string, wg *sync.WaitGroup) {
    defer wg.Done() // 确保在函数返回前调用Done

    resp, err := http.Get(url)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()

    // 处理网页内容...
    fmt.Println("Crawled", url)
}

func main() {
    var wg sync.WaitGroup
    urls := []string{
        "http://example.com",
        "http://example.org",
        "http://example.net",
    }

    for _, url := range urls {
        wg.Add(1) // 在启动goroutine之前调用Add
        go crawl(url, &wg)
    }

    wg.Wait() // 等待所有goroutine完成
    fmt.Println("Crawling finished")
}

关键点解释

  1. 初始化WaitGroup:在main函数中初始化sync.WaitGroup
  2. 调用Add方法:在启动每个goroutine之前,调用wg.Add(1)来增加计数器。
  3. 调用Done方法:在每个goroutine的函数末尾,使用defer wg.Done()来确保计数器在函数返回前减少。
  4. 等待所有goroutine完成:在main函数中调用wg.Wait()来等待所有goroutine完成。

参考链接

通过遵循这些最佳实践,可以有效地避免在使用sync.WaitGroup时出现panic的情况。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券