如何终止从goroutine [duplicate]中调用的函数

问题描述 投票:-3回答:1
    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()执行

go channel
1个回答
0
投票

无法立即终止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
© www.soinside.com 2019 - 2024. All rights reserved.