Identify and stop a goroutine

I’v a problem with one of my program this is the case:

I’v a main program that calls a function (on an external file), this function start a goroutine that runs forever, now, this function can be called different times so more goroutines can be started, i need a way from the main file for identify a goroutine and terminate it only if some requisites match.

E.g.

firstfile.go

func main(){
     if(key_is_pressed){
            myfunction()
     }
     if(Upeercase_key_is_pressed){
               kill_goroutine(id_goroutine_or_something) //i know this is not possible, but just for explain my idea
     }
}

secondfile.go

mygoroutine(Chan, otherstuff){
    for{
          // do stuff
    }
}


myfunction(){
             Chan := make(chan int)
             go mygoroutine (Chan, otherstuff)
}

So in this way i can start an infinite amount of gorouties that will never stop, i need a way to identify them and stop the one i want only if Uppercase_key_is pressed happen

So if a is pressed it creates a goroutine, if b is pressed create a goroutine, same for c, but if i press B it only terminates the correspondent goroutine

My idea is: create another channel only for send END, this channel is called ENDCHANNEL_nameofthekey and is associated to the goroutine,

so my code should be something like

func main(){
     if(key_is_pressed){
            myfunction(keyname)
     }
     if(Uppercase_key_is_pressed){
               kill_goroutine(id_goroutine_or_something) //i know this is not possible, but just for explain my idea
     }
}

file 2

mygoroutine(Chan1, Chan2, otherstuff){
    for{
        // do stuff
       end <-Chan2
       if (end == 1){
           return
        }
     }
}


myfunction(keyname){
    Chan1 := make(chan int)
     Chan+keyname := make (chan int) //is possible to name a channel in this way?
                 go mygoroutine (Chan1, Chan+keyname, otherstuff)
    }

Channels can be stored in maps. The map key can then be used to name the channel.

The other thing to know is that receiving from a closed channel yields the type’s zero value. Therefore closing a channel on which nothing has been sent will cause all receivers for that channel to receive a value.

Here is a quick prototype with simulated key presses:

package main

import (
	"log"
	"time"
	"unicode"
)

func main() {
	log.SetFlags(log.Lshortfile)
	log.Println("started")

	doneChans := map[rune]chan struct{}{}

	i := 0
	for _, r := range []rune{'g', 'k', 'g', 'k', 'G', 'g', 'G'} {
		time.Sleep(time.Second)
		log.Println(string(r))

		if unicode.IsLower(r) {
			log.Println("lower")
			// add a function
			done, ok := doneChans[r]
			if !ok {
				done = make(chan struct{})
				doneChans[r] = done
			}

			go routine(done, i, r)

			i++
			continue
		}

		if unicode.IsUpper(r) {
			log.Println("upper")
			// kill those functions
			lower := unicode.ToLower(r)
			done, ok := doneChans[lower]
			if !ok {
				// there is no done channel, so there are none
				// with that rune running
				continue
			}

			close(done)
			delete(doneChans, lower)

			continue
		}
	}

	select {}
}

func routine(done chan struct{}, i int, r rune) {
	for {
		// do some work
		log.Println(string(r), i, time.Now())
		time.Sleep(500 * time.Millisecond)

		select {
		case <-done:
			log.Println(string(r), i, "done")
			return
		default:
		}
	}
}
2 Likes

Thanks for the clarification, this will solve the problem

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.