Named Goroutine
2 min readJun 19, 2024
package main
import (
"context"
"fmt"
"log"
"reflect"
"strings"
"time"
)
type GoManager struct {
items map[string]context.CancelFunc
}
func NewGoManager() *GoManager {
return &GoManager{
items: make(map[string]context.CancelFunc),
}
}
type FuncType func()
func (GR *GoManager) AddCancelFunc(name string, cancelFunc context.CancelFunc) {
GR.items[name] = cancelFunc
}
func (GR *GoManager) Cancel(name string) {
defer log.Printf("%s being cancelled", name)
gr, ok := GR.items[name]
if ok {
gr()
}
}
func handleContext(ctxgroup ...context.Context) bool {
if len(ctxgroup) > 0 {
if ctx, ok := ctxgroup[0].(context.Context); ok {
// Check if context has cancellation function
if ctxDone := ctx.Done(); ctxDone == nil {
return false
}
return true
}
}
return false
}
func (GR *GoManager) GO(name string, fn interface{}, argv ...interface{}) {
//generic_ctx, cancel := context.
cancelCtx, cancel := context.WithCancel(context.Background())
//defer GR.Cancel(name)
GR.AddCancelFunc(name, cancel)
funcValue := reflect.ValueOf(fn)
if funcValue.Kind() != reflect.Func {
log.Println("fn is not a function", funcValue.Kind())
return
}
args := make([]reflect.Value, funcValue.Type().NumIn())
for i := 0; i < funcValue.Type().NumIn(); i++ {
args[i] = reflect.ValueOf(argv[i])
}
log.Printf("%s being staring", name)
go func(ctx context.Context) {
funcValue.Call(args)
}(cancelCtx)
}
func sum(i int) error {
time.Sleep(time.Duration(i) * time.Second)
log.Printf("%d being done", i)
return nil
}
func times(str string, n int) string {
var res strings.Builder
for i := 0; i < n; i++ {
res.WriteString(str)
}
log.Println(res.String())
return res.String()
}
func main() {
manager := NewGoManager()
alphabet := "abcdefghijklmnop"
for i := 0; i < 7; i++ {
manager.GO(fmt.Sprintf("abc-%d", i), sum, i)
manager.GO(fmt.Sprintf("def-%d", i), times, string(alphabet[i]), i)
}
manager.Cancel("abc-2")
manager.Cancel("def-3")
time.Sleep(3 * time.Second)
log.Println("Hello World")
}
This is first draft version of simple go routine manager which is otherwise difficult to manage. I tried to get it by name or some id and see what is inside it.
In next version, I will try to add more control.I want to create a Future Object , a polling equivalent, a pipeline etc. So keep ideating and improving it. I got a throught to cancel a running goroutine by name and i found a basic solution. I will improve this over weekends