package try import ( "fmt" "reflect" "runtime/debug" ) type TryCatch struct { TryFn interface{} TryParams []interface{} CatchFn interface{} CatchParams []interface{} } type TryInterface interface { Run() SetFn(interface{}) SetCatchFn(fn interface{}) SetTryParams(params []interface{}) SetCatchParams(params []interface{}) } func (t *TryCatch) SetFn(fn interface{}) { t.TryFn = fn } func (t *TryCatch) SetCatchFn(fn interface{}) { t.CatchFn = fn } func (t *TryCatch) SetTryParams(params []interface{}) { t.TryParams = params } func (t *TryCatch) SetCatchParams(params []interface{}) { t.CatchParams = params } func catchFunc(err interface{}) { fmt.Println(fmt.Sprintf("panic : %s\n", err)) fmt.Println(fmt.Sprint(string(debug.Stack()))) } func (t *TryCatch) getParams(params []interface{}) []reflect.Value { realParams := make([]reflect.Value, len(params)) for i, param := range params { realParams[i] = reflect.ValueOf(param) } return realParams } func (t *TryCatch) Run() { go func() { defer func() { if err := recover(); err != nil { defer func() { if err = recover(); err != nil { catchFunc(err) } }() if t.CatchFn != nil { realCatchFunc := reflect.ValueOf(t.CatchFn) errParams := []reflect.Value{} errParams = append(errParams, reflect.ValueOf(err)) for _, param := range t.CatchParams { errParams = append(errParams, reflect.ValueOf(param)) } realCatchFunc.Call(errParams) } else { catchFunc(err) } } }() realFunc := reflect.ValueOf(t.TryFn) realFunc.Call(t.getParams(t.TryParams)) }() } func Go(tryFunc func(), catchFunc func(interface{})) { go func(tryFunc func(), catchFunc func(interface{})) { defer func() { if err := recover(); err != nil { catchFunc(err) } }() tryFunc() }(tryFunc, catchFunc) } /** * tryFunc go func * catchFunc catch func * tryFunc params */ func GoParams(tryFunc interface{}, catchFunc func(interface{}), fnParams ...interface{}) { realFunc := reflect.ValueOf(tryFunc) realParams := make([]reflect.Value, len(fnParams)) for i, param := range fnParams { realParams[i] = reflect.ValueOf(param) } go func(realFunc reflect.Value, catchFunc func(interface{}), realParams []reflect.Value) { defer func() { if err := recover(); err != nil { catchFunc(err) } }() realFunc.Call(realParams) }(realFunc, catchFunc, realParams) }