package tool import ( "context" "log" "reflect" "runtime" "sync" ) func Must(errs ...error) { for _, err := range errs { if err != nil { log.Panic(err.Error()) } } } func MustWithData[T any](data T, err error) T { Must(err) return data } func MustStop(ctx context.Context, stopFns ...func(ctx context.Context) error) { getFunctionName := func(i interface{}) string { return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() } if len(stopFns) == 0 { return } ok := make(chan struct{}) wg := &sync.WaitGroup{} for _, fn := range stopFns { if fn != nil { wg.Add(1) go func(c context.Context) { defer func() { wg.Done() log.Printf("stop func[%s] done", getFunctionName(fn)) }() if err := fn(c); err != nil { log.Printf("stop function failed, err = %s", err.Error()) } }(ctx) } } go func() { select { case <-ctx.Done(): log.Fatal("stop function timeout, force down") case _, _ = <-ok: log.Printf("shutdown gracefully...") return } }() wg.Wait() close(ok) } func IgnoreError[T any](item T, err error) T { if err != nil { log.Printf("[W] !!! ignore error: %s", err.Error()) } return item }