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
}
回到顶部