函数应该在进程在单独的 go routine 中工作时返回输出

问题描述 投票:0回答:1

我有以下代码:

package main

import (
    "errors"
    "fmt"
    "sync"
    "time"

    er "github.com/pkg/errors"
)

func main() {
    var wg sync.WaitGroup
    errorsChan := make(chan error) // remove the length and see the error happens!

    wg.Add(1)
    go func() {
        defer wg.Done()
        
        wg.Add(1)
        go func() {
            defer wg.Done()

            say(5)

            errorsChan <- er.Wrap(errors.New("first one"), "first test")
        }()

        wg.Add(1)
        go func() {
            defer wg.Done()

            say(1)

            errorsChan <- er.Wrap(errors.New("something"), "another test")
        }()
    }()

    go func() {
        wg.Wait()
        close(errorsChan)
    }()

    for item := range errorsChan {
        fmt.Println(item)
    }

    // time.Sleep(10*time.Second)
    fmt.Print("HELLO\n")
}

func say(i time.Duration) {
    time.Sleep(i * time.Second)
}

我想在错误消息之前先打印

HELLO

现在

HELLO
正在等待上面的错误消息,然后被打印出来。 如果我删除顶层
wg.Add(1)
然后我收到错误
panic: send on closed channel

我应该做出什么改变?

go goroutine
1个回答
0
投票

阅读代码后,我找到了解决方案。

i 应该将

wg.Wait()
close(errorsChan)
代码放在顶级 go 例程中。因为这是需要
errorsChan
的地方,所以打印
HELLO
可以在主要的 go 程序中进行。

所以正确答案如下:

 package main
    
    import (
        "errors"
        "fmt"
        "sync"
        "time"
    
        er "github.com/pkg/errors"
    )
    
    func main() {
        var wg sync.WaitGroup
        errorsChan := make(chan error) // remove the length and see the error happens!
    
        wg.Add(1)
        go func() {
            defer wg.Done()
            
            wg.Add(1)
            go func() {
                defer wg.Done()
    
                say(5)
    
                errorsChan <- er.Wrap(errors.New("first one"), "first test")
            }()
    
            wg.Add(1)
            go func() {
                defer wg.Done()
    
                say(1)
    
                errorsChan <- er.Wrap(errors.New("something"), "another test")
            }()

go func() {
            wg.Wait()
            close(errorsChan)
        }()
    
        for item := range errorsChan {
            fmt.Println(item)
        }
        }()
    
        
    
        // time.Sleep(10*time.Second)
        fmt.Print("HELLO\n")
    }
    
    func say(i time.Duration) {
        time.Sleep(i * time.Second)
    }
© www.soinside.com 2019 - 2024. All rights reserved.