首页 > 解决方案 > 是否可以从外部函数中停止代码/goroutine?

问题描述

所以,我有这个(只是一个例子):

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(5 * time.Second)
    for {
        select {
        case <-ticker.C:
            fmt.Println("hello")
        }
    }
}

这是一个无限循环,我想要这样。在实际代码中,它每 1 小时循环一次。但是,如果我想调用一个函数来让它停止循环呢?这可能吗?就像是:

func stop() {
//this will stop the main function from looping
}

我知道我可以做类似的事情:

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(5 * time.Second)
    done := make(chan bool)
    go func() {
        for {
            select {
            case <-done:
                fmt.Println("done")
                ticker.Stop()
                return
            case <-ticker.C:
                fmt.Println("hello")
            }
        }
    }()

    time.Sleep(10 * time.Second)
    done <- true
}

但这将从预定义的时间范围(在本例中为 10 秒)停止该函数,这不是我想要的,而且这都在同一个函数中,我需要从主函数外部进行调用。

这有可能吗?

标签: loopsgoconcurrencygoroutine

解决方案


这里:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func stop(ch chan<- struct{}) {
    select {
    // Triggers after 7 seconds
    case <-time.After(7 * time.Second):
        ch <- struct{}{}
    }
}

func signalStop(ch chan<- struct{}) {
    // Use a buffered channel (size = 1)
    sig := make(chan os.Signal, 1)
    // Use SIGINT signal i.e.,  <kill -SIGINT XXXX> or <Control+C>
    signal.Notify(sig, syscall.SIGINT)
    select {
    // Capture the SIGINT signal
    case <-sig:
        // Close the channel
        close(ch)
    }
}

func main() {
    ticker := time.NewTicker(1 * time.Second)
    done := make(chan struct{})
    // Spawn a goroutine with the done channel
    go signalStop(done)
    for {
        select {
        case <-ticker.C:
            fmt.Println("Hello!")
        case <-done:
            // When stop signals, stop the ticker and return
            ticker.Stop()
            fmt.Println("Bye, bye!")
            return
        }
    }
}

我已经注释了代码的相关部分,以便您了解我想要做什么。


推荐阅读