函数应该在进程在单独的Go协程中运行时返回输出。

huangapple go评论85阅读模式
英文:

function should return the output while the process works in a separate go routine

问题

我有以下代码:

package main

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

	er "github.com/pkg/errors"
)

func main() {
	var wg sync.WaitGroup
	errorsChan := make(chan error)

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

	fmt.Print("HELLO\n")
}

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

我想先打印出HELLO,然后再打印错误消息。

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

我应该做什么改变?

英文:

I have the following code:

package main

import (
	&quot;errors&quot;
	&quot;fmt&quot;
	&quot;sync&quot;
	&quot;time&quot;

	er &quot;github.com/pkg/errors&quot;
)

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 &lt;- er.Wrap(errors.New(&quot;first one&quot;), &quot;first test&quot;)
		}()

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

			say(1)

			errorsChan &lt;- er.Wrap(errors.New(&quot;something&quot;), &quot;another test&quot;)
		}()
	}()

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

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

	// time.Sleep(10*time.Second)
	fmt.Print(&quot;HELLO\n&quot;)
}

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

I want to print HELLO first before the error messages.

Right now HELLO is waiting for the above error messages, and then gets printed.
and if I remove the top level wg.Add(1) then I am getting the error panic: send on closed channel

What is the change that I should make?

答案1

得分: 1

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

我应该将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)
}

希望对你有帮助!

英文:

After a bit of reading through the code, i found the solution.

i should put the wg.Wait() and close(errorsChan) code inside the top level go routine. Since it is were the errorsChan is needed, and the printing HELLO can be on the main go routine.

so the corrected answer will be like below:

 package main
    
    import (
        &quot;errors&quot;
        &quot;fmt&quot;
        &quot;sync&quot;
        &quot;time&quot;
    
        er &quot;github.com/pkg/errors&quot;
    )
    
    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 &lt;- er.Wrap(errors.New(&quot;first one&quot;), &quot;first test&quot;)
            }()
    
            wg.Add(1)
            go func() {
                defer wg.Done()
    
                say(1)
    
                errorsChan &lt;- er.Wrap(errors.New(&quot;something&quot;), &quot;another test&quot;)
            }()

go func() {
            wg.Wait()
            close(errorsChan)
        }()
    
        for item := range errorsChan {
            fmt.Println(item)
        }
        }()
    
        
    
        // time.Sleep(10*time.Second)
        fmt.Print(&quot;HELLO\n&quot;)
    }
    
    func say(i time.Duration) {
        time.Sleep(i * time.Second)
    }

huangapple
  • 本文由 发表于 2023年3月8日 00:41:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75664816.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定