Arjun Ajith
Arjun Ajith

Reputation: 1920

How to stop goroutine from client?

I need to create a html page which has two buttons, one will start a goroutine, which has an infinite loop, and other button need to break the infinite loop. As from my readings I understood that a goroutine can't be killed from outside it. Is there anyway to implement this? My code is as follows:

command := c.GetString("command") // from client to determine which button is clicked
quit := make(chan bool)
switch command {
    case "start":    // Button to start goroutine
        go func() {
            i := 0
            for {
                select {
                    case <- quit:
                        return
                     default:
                         fmt.Println("i: ", i)
                         i++
                         time.Sleep(3000 * time.Millisecond)
                 }
             }
         }()
     case "stop":    // Button to stop goroutine
         quit <- true
}

Upvotes: 1

Views: 461

Answers (1)

abhink
abhink

Reputation: 9136

You are already right about the design. An issue is that you are creating new channels each time you recieve a command. Which means there is no way to communicate with the previously started goroutine. You need to have a quit channel that stays in scope for between requests. Try something like below (untested):

func listenForCommand() {
    var quit chan bool

    for {
        // command receiver, should fire for each command received
        command := c.GetString("command")

        switch command {
        case "start":
            if quit != nil {
                continue
            }
            quit = make(chan bool)
            go func() {
                i := 0
                for {
                    select {
                    case <-quit:
                        return
                    default:
                        fmt.Println("i: ", i)
                        i++
                        time.Sleep(3000 * time.Millisecond)
                    }
                }
            }()
        case "stop":
            if quit == nil {
                continue
            }
            quit <- true
            close(quit)
            quit = nil
        }
    }
}

You can now call listenForCommand() to start listening for commands. This example presumes that there is another process populating c so c.GetString("command") returns a command if available, or blocks and waits for a command to arrive.

Upvotes: 1

Related Questions