Golang中channel是否能保证goroutine执行完成?
Golang中channel是否能保证goroutine执行完成? 那么,在Go中使用通道是否就能保证所有goroutine都执行完毕,还是我们仍然需要使用等待组呢? 我写了以下代码,其中包含一个监听信号的goroutine。
package main
import (
"fmt"
"os"
"os/exec"
"os/signal"
"sync"
"syscall"
)
var pid int
var wg sync.WaitGroup
func main() {
signl := make(chan os.Signal, 1)
signal.Notify(signl)
go func() {
wg.Add(1)
defer wg.Done()
for {
sig := <-signl
if sig == syscall.SIGINT && pid != 0 {
cmd := exec.Command("minikube", "stop")
err := cmd.Start()
fmt.Println("closed minikube")
if err != nil {
fmt.Println("failed to close minikube : ", err)
}
os.Exit(1)
}
fmt.Println("unknown signal recieveed : ", sig)
}
}()
cmd1 := exec.Command("minikube", "start")
err := cmd1.Start()
if err != nil {
fmt.Println("failed to start minikube : ", err)
}
cmd1.Wait()
fmt.Println("starting dashboard...")
cmd2 := exec.Command("minikube", "dashboard")
err = cmd2.Start()
pid = cmd2.Process.Pid
fmt.Println("pid", pid)
if err != nil {
fmt.Println("failed to open dashboard : ", err)
}
wg.Wait()
}
在上面的代码中,等待组是无用的吗?
更多关于Golang中channel是否能保证goroutine执行完成?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
非常感谢,这非常有帮助。
更多关于Golang中channel是否能保证goroutine执行完成?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你好。在上面的代码中,你的程序在 goroutine 退出之前不会退出。由于 goroutine 内部有一个无限循环,它永远不会自行退出。一切取决于你具体想实现什么以及如何实现。如果是为了优雅关闭以执行一些清理操作之类的,我通常会使用类似下面的方法:
func exitCtx(parent context.Context) (context.Context, context.CancelFunc) {
ctx, cancel := context.WithCancel(parent)
go func() {
osSignalCh := make(chan os.Signal, 1)
defer func() {
cancel()
signal.Stop(osSignalCh)
close(osSignalCh)
}()
signal.Notify(
osSignalCh,
syscall.SIGINT,
syscall.SIGTERM,
os.Interrupt,
)
select {
case <-ctx.Done():
return
case <-osSignalCh:
fmt.Println()
return
}
}()
return ctx, cancel
}
如果你只是想在一个 goroutine 中执行一些代码,然后在所有代码执行完毕后退出程序,那么是的,你需要自己进行同步,因为一旦主函数退出,goroutine 就会被终止。可以像这样:
func DoSomething(ctx context.Context) chan error {
done := make(chan error, 1)
go func() {
defer close(done)
errBuf := errbuf.NewErrorsBuffer()
var wg sync.WaitGroup
wg.Add(numOfProcesses)
for i := 0; i < numOfProcesses; i++ {
go func() {
defer wg.Done()
for j := range dataChannel {
if err := doTheThing(j); err != nil {
errBuf.Add(err)
}
}
}()
}
wg.Wait()
done <- errBuf.Err()
}()
return done
}

