Go语言的协程中,写死循环的注意点

先来看一段代码:

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 {
    
    
	}
}

按常规思维会认为程序输出10个t1和10个t2就不会再输出任何东西了,因为T1()、T2()这两个方法执行完以后,Test的实例就没有任何引用的地方,那么Go的垃圾回收机制就会销毁这两个实例,对应的协程也会销毁了。但事实总是出奇的和预想相反,这个程序会一直输出t1和t2,所以协程中的死循环一定要写一个退出机制。

方案1,设置一个变量来标识循环是否停止:

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 {
    
    
	}
}

方案2,用退出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 {
    
    

	}
}

总之,在go协程中写死循环一定要写退出机制。

おすすめ

転載: blog.csdn.net/m0_46455711/article/details/111396915