package main
import (
"context"
"errors"
"fmt"
"time"
)
type result struct {
record interface{}
err error
}
func longRun() {
for i := 0; ; i++ {
time.Sleep(1 * time.Second)
fmt.Println("This is very long running ", i)
}
}
func process() (interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
quit := make(chan int)
go func() {
for {
select {
case <-quit:
fmt.Println("quit")
return
default:
longRun()
return
}
}
}()
select {
case <-ctx.Done():
close(quit)
return nil, errors.New("Execution canceled")
}
}
func main() {
value, err := process()
fmt.Println("value", value)
fmt.Println("err", err)
//prevent main function termination
for i := 0; ; i++ {
}
}
超时时,process()函数中的goroutine终止,但是我如何终止longrun()函数。
样本输出
This is very long running 0
This is very long running 1
value <nil>
err Execution canceled
This is very long running 2
This is very long running 3
This is very long running 4
正如输出所表明的,即使在返回流程函数之后,longrun()函数仍在执行。
如何返回process()函数后立即终止longrun()执行
无法立即终止goroutine。您可以使用上下文将取消通知发送到goroutine,但是goroutine必须定期检查上下文并在上下文被取消时终止。您可以等待长时间运行的goroutine终止,然后再使用另一个通道从函数返回:
func longRunning(ctx context.Context,done chan struct{}) {
defer close(done)
for {
...
select {
case <-ctx.Done():
return
default:
}
}
}
...
ctx, cancel:=context.WithCancel(context.Background())
defer cancel()
ch:=make(chan struct{})
go longRunning(ctx,ch)
// Do things
cancel() // Stop goroutine
// wait for the long running to terminate
<-ch