小编典典

终止第二个goroutine

go

我有以下代码片段。

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上的通道仍在等待错误引用,这意味着,它浪费了内存,没有任何等待。

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


阅读 265

收藏
2020-07-02

共1个答案

小编典典

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

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
2020-07-02