登录
首页 >  Golang >  Go问答

golang:除非我添加了 fmt.Print(),否则带有 select 的 goroute 不会停止

来源:Golang技术栈

时间:2023-03-28 11:54:54 291浏览 收藏

亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《golang:除非我添加了 fmt.Print(),否则带有 select 的 goroute 不会停止》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下golang,希望所有认真读完的童鞋们,都有实质性的提高。

问题内容

我尝试了 Go Tour练习 #71

如果它像 一样运行go run 71_hang.go ok,它工作正常。

但是,如果您使用go run 71_hang.go nogood,它将永远运行。

唯一的区别是语句fmt.Print("")default的额外内容。select

我不确定,但我怀疑某种无限循环和竞争条件?这是我的解决方案。

注意:这不是死锁,因为 Go 没有throw: all goroutines are asleep - deadlock!

package main

import (
    "fmt"
    "os"
)

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)
}

func crawl(todo Todo, fetcher Fetcher,
    todoList chan Todo, done chan bool) {
    body, urls, err := fetcher.Fetch(todo.url)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Printf("found: %s %q\n", todo.url, body)
        for _, u := range urls {
            todoList  0 && !visited[todo.url] {
                crawling++
                visited[todo.url] = true
                go crawl(todo, fetcher, toDoList, doneCrawling)
            }
        case 

正确答案

以select 的工作方式default在您的更改中添加声明。select如果没有默认语句,select 将阻止等待通道上的任何消息。使用默认语句 select 将在每次从通道中读取任何内容时运行默认语句。在您的代码中,我认为这是一个无限循环。放入该fmt.Print语句是允许调度程序调度其他 goroutines。

如果您像这样更改您的代码,那么它可以正常工作,以非阻塞方式使用 select,从而允许其他 goroutine 正常运行。

    for {
        select {
        case todo :=  0 && !visited[todo.url] {
                crawling++
                visited[todo.url] = true
                go crawl(todo, fetcher, toDoList, doneCrawling)
            }
        case 

如果您使用 GOMAXPROCS=2 可以使您的原始代码工作,这是调度程序在无限循环中忙碌的另一个提示。

请注意,goroutine 是协作调度的。我对您的问题不完全理解的是,这select是 goroutine 应该让步的地方 - 我希望其他人可以解释为什么它不在您的示例中。

今天关于《golang:除非我添加了 fmt.Print(),否则带有 select 的 goroute 不会停止》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于golang的内容请关注golang学习网公众号!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>