In the Go language's coroutine, the points to note when writing an infinite loop

First look at a piece of code:

type Test struct {
    
    
	Name string
}
func NewTest(n string) *Test  {
    
    
	return &Test{
    
    
		Name: n,
	}
}
func (t *Test) Start()  {
    
    
	go func() {
    
    
		for {
    
    
			print(t.Name)
			time.Sleep(1*time.Second)
		}
	}()
}
func T1()  {
    
    
	t1:=NewTest("t1 ")
	t1.Start()
	time.Sleep(10*time.Second)
}
func T2()  {
    
    
	t2:=NewTest("t2 ")
	t2.Start()
	time.Sleep(10*time.Second)
}
func main() {
    
    
	T1()
	T2()
	select {
    
    
	}
}

According to conventional thinking, you will think that the program will output 10 t1 and 10 t2, and nothing will be output, because after the two methods of T1() and T2() are executed, there is no place to reference the Test instance, then Go's garbage collection mechanism will destroy these two instances, and the corresponding coroutine will also be destroyed. But the facts are always surprising and contrary to expectations, this program will always output t1 and t2, so the infinite loop in the coroutine must write an exit mechanism.

Option 1, set a variable to identify whether the loop stops:

type Test struct {
    
    
	Name string
	B bool
}
func NewTest(n string) *Test  {
    
    
	return &Test{
    
    
		Name: n,
		B:true,
	}
}
func (t *Test) Start()  {
    
    
	go func() {
    
    
		for t.B{
    
    
			print(t.Name)
			time.Sleep(1*time.Second)
		}
	}()
}
func T1()  {
    
    
	t1:=NewTest("t1 ")
	t1.Start()
	time.Sleep(10*time.Second)
	t1.B=false
}

func T2()  {
    
    
	t1:=NewTest("t2 ")
	t1.Start()
	time.Sleep(10*time.Second)
	t1.B=false
}

func main() {
    
    
	T1()
	T2()
	select {
    
    
	}
}

Option 2, use exit chan:

package main
import "time"
type Test struct {
    
    
	Name string
	t *time.Ticker
	quitChan chan struct{
    
    }
}
func NewTest(n string) *Test  {
    
    
	return &Test{
    
    
		Name: n,
		t:time.NewTicker(1*time.Second),
		quitChan: make(chan struct{
    
    }),
	}
}
func (t *Test) Start()  {
    
    
	go func() {
    
    
		for {
    
    
			select {
    
    
			case <-t.t.C:
				print(t.Name)
			case <-t.quitChan:
				return
			}
		}
	}()
}
func T1()  {
    
    
	t1:=NewTest("t1 ")
	t1.Start()
	time.Sleep(10*time.Second)
	t1.quitChan<- struct{
    
    }{
    
    }
}
func T2()  {
    
    
	t2:=NewTest("t2 ")
	t2.Start()
	time.Sleep(10*time.Second)
	t2.quitChan<- struct{
    
    }{
    
    }
}
func main() {
    
    
	T1()
	T2()
	select {
    
    

	}
}

In short, writing an infinite loop in a go coroutine must write an exit mechanism.

Guess you like

Origin blog.csdn.net/m0_46455711/article/details/111396915