当前位置: 首页 > 面试题库 >

终止第二个goroutine

顾涵衍
2023-03-14
问题内容

我有以下代码片段。

package main

import (
    "errors"
    "fmt"
    "time"
)

func errName(ch chan error) {

    for i := 0; i < 10000; i++ {

    }

    ch <- errors.New("Error name")
    close(ch)
}

func errEmail(ch chan error) {

    for i := 0; i < 100; i++ {

    }
    ch <- errors.New("Error email")
    close(ch)
}

func main() {

    ch := make(chan error)

    go errName(ch)
    go errEmail(ch)
    fmt.Println(<-ch)
    //close(ch)

    time.Sleep(1000000)

}

如您所见,我在goroutine中运行了两个函数errName和errEmail。我将错误类型的通道作为参数传递。如果其中一个先完成,它应该通过通道发送错误并关闭它。因此,第二个仍在运行的goroutine不再需要运行,因为我已经遇到了错误,并且我想终止仍在运行的goroutine。这就是我在上面的示例中尝试达到的目标。

当我运行程序时,出现错误

panic: send on closed channel

goroutine 6 [running]:
main.errEmail(0xc0820101e0)
        D:/gocode/src/samples/gorountine2.go:24 +0xfd
created by main.main
        D:/gocode/src/samples/gorountine2.go:33 +0x74

goroutine 1 [runnable]:
main.main()
        D:/gocode/src/samples/gorountine2.go:34 +0xac
exit status 2

我知道,当我删除close语句时,它不会死机,但是正在运行的goroutine上的通道仍在等待错误引用,这意味着,它浪费了内存,没有任何等待。

当其中一个向通道发送错误时,我不再关心第二个错误,那就是我的目标。


问题答案:

组织这种行为的标准方法是使用

package main

import (
    "fmt"
    "time"

    "code.google.com/p/go.net/context"
)

func errName(ctx context.Context, cancel context.CancelFunc) {
    for i := 0; i < 10000; i++ {
        select {
        case <-ctx.Done():
            return
        default:
        }
    }
    cancel()
}

func errEmail(ctx context.Context, cancel context.CancelFunc) {

    for i := 0; i < 100; i++ {
        select {
        case <-ctx.Done():
            return
        default:
        }
    }
    cancel()
}

func main() {

    ctx := context.Background()

    ctx, cancel := context.WithCancel(ctx)

    go errName(ctx, cancel)
    go errEmail(ctx, cancel)

    <-ctx.Done()

    if ctx.Err() != nil {
        fmt.Println(ctx.Err())
    }

    time.Sleep(1000000)

}

您可以阅读有关此问题的两篇好文章:

  1. http://blog.golang.org/context
  2. http://blog.golang.org/pipelines


 类似资料:
  • 问题内容: 我需要启动大量goroutine,并等待其终止。直观的方法似乎是使用通道来等待所有操作完成: 但是问题是对象的数量以及goroutine的数量可能会改变。是否可以更改通道的缓冲区大小? 也许有更优雅的方式做到这一点? 问题答案: 我已经使用WaitGroup作为此问题的解决方案。翻译您的当前代码,并附上一些日志,以明确正在发生的事情:

  • 终止容器 可以使用 docker container stop 来终止一个运行中的容器。 此外,当 Docker 容器中指定的应用终结时,容器也自动终止。 例如对于上一章节中只启动了一个终端的容器,用户通过 exit 命令或 Ctrl+d 来退出终端时,所创建的容器立刻终止。 终止状态的容器可以用 docker container ls -a 命令看到。例如 docker container ls

  • 它的工作很好,但当我把它封闭在我的如果不喜欢 这给了我一个例外: org.apache.jasper.jasperexception:/jsp/custmngmt/reports/viewCustomerDepositReportCriteriaForOldReceipt.jsp(356,0)未终止 我已经测试了条件,它确实输入了if部分,但在通过form标记时会导致异常。我不明白。请帮帮我。

  • 2.4 频道终止 2.4.1 描述 通过调用该接口终止指定的域名的加速服务。 2.4.2 请求地址 地址:https://api.bokecs.com/channel/delete/{channelId} 2.4.3 请求方式 POST 2.4.4 请求参数 1) 请求入参 channelId 频道唯一标识 2)请求出参 { "code": "", "message": "" } code:接口

  • 部署项目后,当客户机第一次向TestServlet发送请求时,server会创建TestServlet对象,然后调用第一个init()方法(init(ServletConfig config))。然后JVM检查TestServlet中的第一个init()方法,因为它不可用,然后它检查超级类HttpServlet,第一个init方法也不可用,然后JVM检查HttpServlet的超级类,即Gener

  • 先尝试用 D3 写第一个 HelloWorld 程序。学编程入门的第一个程序都是在屏幕上输出 HelloWorld,本课稍微有些不同,不是单纯的输出。 HTML 是怎么输出 HelloWorld 的 都知道 HTML 吧,如果不知道请下百度一下吧。在 HTML 中输出 HelloWorld 是怎样的呢,先看下面的代码。 <html> <head> <meta charset="