Je développe une API backend en couches avec des contrôleurs, des services, des référentiels, etc.
Chaque méthode de ces couches prend context.Context
comme premier paramètre contenant le contexte de requête. C'est pratique car n'importe quelle méthode peut accéder à diverses données liées à la requête (telles que l'ID de corrélation, etc.)
Chaque contexte de requête a un délai d'attente défini par TimeoutMiddleware
ci-dessous :
func TimeoutMiddleware(timeoutFn func(*gin.Context) time.Duration) gin.HandlerFunc { return func(c *gin.Context) { timeout := timeoutFn(c) ctx, cancel := context.WithTimeout(c.Request.Context(), timeout) defer cancel() c.Request = c.Request.WithContext(ctx) c.Next() } } func TimeoutFn(c *gin.Context) time.Duration { return conf.HTTPRouter.DefaultContextTimeout }
L'idée est d'arrêter gracieusement toutes les opérations en cours lorsque le contexte de la demande expire. Sur la base de ma compréhension du contexte et de la concurrence (très peu), j'ai construit cette fonction d'assistance :
package helpers import "context" // Checks for context cancellation and returns ctx.Err() if canceled. func HandleContextCancel(ctx context.Context) error { select { case <-ctx.Done(): // If the context is canceled return ctx.Err() // return immediately with the canceled error. default: return nil // Continue with the normal processing. } }
Théoriquement, si je voulais arrêter toute opération dès que possible , j'aurais besoin d'appeler cette fonction < /p> au début
de chaque méthode de l'application, comme ceci :
func DoSomething(ctx context.Context, ...) resterrors.RestErr {
if err := helpers.HandleContextCancel(ctx); err != nil {
return resterrors.NewRequestTimeoutError(
fmt.Errorf("DoSomething: %w", err),
)
}
// ...
Query
、QueryRow
、Exec
contexte
..., comme ceci : internal_server_error
rows, err := pgclient.GetSession().Query(ctx, query, param1, ...)
et un message d'erreur comme celui-ci : HandleContextCancel
函数看起来有点多余,您对此有何看法?
您不需要 HandleContextCancel
rows, err := pgclient.GetSession().Query(ctx, query, param1, ...) if err != nil { return helpers.MapRepoError("DoSomething: Query Error:", err) }
func MapRepoError(location string, err error) resterrors.RestErr { if errors.Is(err, context.DeadlineExceeded) { return resterrors.NewRequestTimeoutError( fmt.Errorf("%s request_timeout", location), ) } return resterrors.NewInternalServerError( fmt.Errorf("%s %w", location, err), ) }
HandleContextCancel
semble un peu redondant, qu'en pensez-vous ? Unwrap() error
HandleContextCancel
, vous pouvez simplement faire ce qui suit : 🎜
if ctx.Err()!=nil { // Context timed out or canceled. Return return ctx.Err() }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!