有没有办法停止长时间阻塞功能?

我有一个运行几分钟的函数,我正在尝试找到一种方法来使用通道停止它。


我想我不能像在下面的代码中那样做,因为我认为它select只会stop在default完成后处理这种情况。


package main


import (

    "fmt"

    "time"

)


func main() {

    stop := make(chan int)


    go func() {

        for {

            select {

            case <-stop:

                fmt.Println("return")

                return

            default:

                fmt.Println("block")

                time.Sleep(5 * time.Second) // simulate a long running function

                fmt.Println("unblock")

            }

        }

    }()


    time.Sleep(1 * time.Second)

    stop <- 1

}


互换的青春
浏览 213回答 3
3回答

繁华开满天机

我认为你做不到:从某种意义上说,Go 中的 goroutine 是合作的:直到一个 goroutine主动尝试以某种方式确定它是否应该退出,否则没有办法强迫它这样做。我会说它实际上是一个特性,因为如果你可以强行获取一个长时间运行的 goroutine,你将无法确保它干净地退出,即正确释放它获得的所有资源。因此,要么接受这个(例如,如果您的进程想要退出,只需等待该 goroutine 完成)或对其进行重构,以便它定期检查是否发出退出信号。或者甚至考虑将它执行的任务卸载到外部进程(但请注意,虽然终止进程以释放它从操作系统获取的资源是安全的,但对于进程可能已经更新的外部数据而言是不安全的——如文件)。

富国沪深

如果您以某种方式使您的功能可中断,您只能这样做,即您无法自行停止阻塞调用。如果您自己编写阻塞函数,您通常可以使用多个案例和通道来设计一个选择。你的例子看起来像package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; stop := make(chan int)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("block")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-time.After(5 * time.Second):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("unblock")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-stop:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("stopped")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }()&nbsp; &nbsp; time.Sleep(2 * time.Second)&nbsp; &nbsp; stop <- 1&nbsp; &nbsp; // this is just to give the goroutine time to write "stopped" before we exit&nbsp; &nbsp; select{}}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go