drlq92444 2017-03-02 15:58
浏览 96
已采纳

我如何杀死goroutine

I have the following setup:

func startsMain (){
    go main ()
}

fun stopMain (){
    //kill main
}

func main() {
    //infinite loop 
}

I am creating cucumber steps and I need to be able to start and shut down the application.

  • 写回答

1条回答 默认 最新

  • dongren7374 2017-03-02 17:08
    关注

    You can kill you infinite loop using select and channels!

    var quit chan struct{}
    
    func startLoop() {
        quit := make(chan struct{})
        go loop()
    }
    
    func stopLoop() {
        // As mentioned by Kaedys
        //close(quit)
        // permits signalling everyone havins such a `case <-quit:`
        // statement to be stopped at once, which might be even better.
        quit <- struct{}{}
    }
    
    // BTW, you cannot call your function main, it is reserved
    func loop() {
        for {
            select {
            case <-quit:
                break
            default:
                // do stuff. I'd call a function, for clarity:
                do_stuff()
            }
        }
    }
    

    Nice piece of Go swap, ain't it?

    Now, what is this strange chan struct{}? It is a zero-sized channel. We can only fill it with empty structs (that is: struct{}{}). It could be a chan bool or whatever else, since we don't use the content of the channel. The important point is that we use the quit channel to notify the infinite loop in our goroutine that it is time to stop.

    The select statement is used to catch what comes out of channels. It is a blocking statement (that will halt the execution until something is put in one of the channels surveyed by a case), unless you put a default statement. In this situation, every time the select is executed, the loop will break if something was put inside quit, or do_stuff() will be called. You already know this if you've been through the Go Tour.

    Other cool concurrency patterns can be found on the Go Blog.

    Finally, for further fun, you can ask your do_stuff function to be executed at regular time intervals by using Tickers, instead of consuming 100% CPU, like so:

    import "time"
    
    // [...]
    
    func loop() {
        // This ticker will put something in its channel every 2s 
        ticker := time.NewTicker(2 * time.Second)
        // If you don't stop it, the ticker will cause memory leaks
        defer ticker.Stop()
        for {
            select {
            case <-quit:
                return
            case <-ticker.C:
                // do stuff. I'd call a function, for clarity:
                do_stuff()
            }
        }
    }
    

    Here, select is blocking, since we removed the default statement.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路
  • ¥15 公交车和无人机协同运输
  • ¥15 stm32代码移植没反应
  • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
  • ¥100 连续两帧图像高速减法