Home  >  Article  >  Backend Development  >  How to close golang coroutine

How to close golang coroutine

尚
Original
2019-12-28 10:14:587352browse

How to close golang coroutine

1. Pass the exit signal through Channel

Channel is a basic data type of go. It has 3 basic states: nil, open, closed.

Share data through Channel instead of sharing data through shared memory. The main process can send a stop signal to any goroutine through the channel, like the following:

func run(done chan int) {
        for {
                select {
                case <-done:
                        fmt.Println("exiting...")
                        done <- 1
                        break
                default:
                }
 
                time.Sleep(time.Second * 1)
                fmt.Println("do something")
        }
}
 
func main() {
        c := make(chan int)
 
        go run(c)
 
        fmt.Println("wait")
        time.Sleep(time.Second * 5)
 
        c <- 1
        <-c
 
        fmt.Println("main exited")
}

2. Use waitgroup

Normally, we use waitgroup like the following :

1. Create an instance of Waitgroup, assuming we call it wg

2. When each goroutine starts, call wg.Add(1). This operation can be done in Called before goroutine starts, it can also be called inside goroutine. Of course, you can also call wg.Add(n)

3 before creating n goroutines. When each goroutine completes its task, call wg.Done()

4. Wait for all The goroutine calls wg.Wait(), which blocks before all goroutines that have executed wg.Add(1) have called wg.Done(). It will return after all goroutines have called wg.Done().

Example:

type Service struct {
        // Other things
 
        ch        chan bool
        waitGroup *sync.WaitGroup
}
 
func NewService() *Service {
	s := &Service{
                // Init Other things
                ch:        make(chan bool),
                waitGroup: &sync.WaitGroup{},
	}
 
	return s
}
 
func (s *Service) Stop() {
        close(s.ch)
        s.waitGroup.Wait()
}
 
func (s *Service) Serve() {
        s.waitGroup.Add(1)
        defer s.waitGroup.Done()
 
        for {
                select {
                case <-s.ch:
                        fmt.Println("stopping...")
                        return
                default:
                }
                s.waitGroup.Add(1)
                go s.anotherServer()
	}
}
func (s *Service) anotherServer() {
        defer s.waitGroup.Done()
        for {
                select {
                case <-s.ch:
                        fmt.Println("stopping...")
                        return
                default:
                }
 
                // Do something
        }
}
 
func main() {
 
        service := NewService()
        go service.Serve()
 
        // Handle SIGINT and SIGTERM.
        ch := make(chan os.Signal)
        signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
        fmt.Println(<-ch)
 
        // Stop the service gracefully.
        service.Stop()
}

For more golang knowledge, please pay attention to the golang tutorial column.

The above is the detailed content of How to close golang coroutine. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn