package main import ( "context" "log" "net/http" "time" "git.vinchent.xyz/vinchent/go-web/framework" ) // func FooControllerHandler(ctx *framework.Context) error { // return ctx.WriteJSON(http.StatusOK, map[string]any{ // "code": 0, // }) // } func FooControllerHandler(ctx *framework.Context) error { durationCtx, cancel := context.WithTimeout(ctx.BaseContext(), time.Duration(1*time.Second)) defer cancel() finish := make(chan struct{}, 1) panicChan := make(chan interface{}, 1) // some long task go func() { // Deal with the panic during the work defer func() { if p := recover(); p != nil { panicChan <- p } }() // do the business time.Sleep(10 * time.Second) ctx.WriteJSON(http.StatusOK, "ok") finish <- struct{}{} }() select { case <-panicChan: // Protect ResponseWriter for concurrently writing from different // goroutines if there are any ctx.WriterMux().Lock() defer ctx.WriterMux().Unlock() log.Println("panicked") ctx.WriteJSON(http.StatusInternalServerError, "panicked") case <-finish: log.Println("finished") case <-durationCtx.Done(): ctx.WriterMux().Lock() defer ctx.WriterMux().Unlock() log.Println("Timeout") ctx.WriteJSON(http.StatusInternalServerError, "time out") ctx.SetHasTimeout() } return nil } func UserLoginController(ctx *framework.Context) error { ctx.WriteJSON(http.StatusOK, "ok") return nil } func SubjectDelController(ctx *framework.Context) error { ctx.WriteJSON(http.StatusAccepted, "deleted") return nil } func SubjectUpdateController(ctx *framework.Context) error { ctx.WriteJSON(http.StatusAccepted, "updated") return nil } func SubjectGetController(ctx *framework.Context) error { ctx.WriteJSON(http.StatusAccepted, "got") return nil } func SubjectListController(ctx *framework.Context) error { ctx.WriteJSON(http.StatusAccepted, "list") return nil }