英文:
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 (
"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)
}
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 (
"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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论