转到频道-这里发生了什么

时间:2019-04-25 23:30:04

标签: go

我正在从有关网络爬虫练习的Go Tour示例中学习go频道。

我的理解是

go func ()

在后台运行func,如果没有阻塞,则只需完成func然后返回即可。

但是下面的go Crawl()似乎什么也没做。我了解这个权利吗?

package main

import (
    "fmt"
)

type Fetcher interface {
    // Fetch returns the body of URL and
    // a slice of URLs found on that page.
    Fetch(url string) (body string, urls []string, err error)
}

// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
    // TODO: Fetch URLs in parallel.
    // TODO: Don't fetch the same URL twice.
    // This implementation doesn't do either:
    if depth <= 0 {
        return
    }
    body, urls, err := fetcher.Fetch(url)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("found: %s %q\n", url, body)
    for _, u := range urls {
        fmt.Println("u is ", u)
        go Crawl(u, depth-1, fetcher)
    }
    return
}

func main() {
    Crawl("https://golang.org/", 4, fetcher)
}

// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult

type fakeResult struct {
    body string
    urls []string
}

func (f fakeFetcher) Fetch(url string) (string, []string, error) {
    if res, ok := f[url]; ok {
        return res.body, res.urls, nil
    }
    return "", nil, fmt.Errorf("not found: %s", url)
}

1 个答案:

答案 0 :(得分:2)

main包的main方法返回时,Go程序终止。这样做后,程序(包括所有goroutine)立即退出。参见Go language spec

  

通过初始化主程序包然后调用函数main开始程序执行。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。

在这种情况下,您的Crawl方法产生多个goroutine,并立即返回,而无需同步这些goroutine以等待它们完成。这样做之后,控制流返回到main,到达函数的末尾并隐式返回,从而暂停程序。请注意,这种交错行为不是确定性的-在某些情况下,您可以从中获取某些goroutine的输出,但是不太可能如此迅速地安排它们的执行。

您需要为Crawl实现一种机制,以阻止等待它产生的goroutine的结果。有几种执行此操作的机制,最常见和推荐的方法是使用WaitGroup