Named Goroutine

Vikas Avnish
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

--

--