The concept of middlewares in gin is really powerful. Of course it's nothing exceptional, most of frameworks have it, but still. For example, custom error reporting is trivially implemented this way.
it's something like
r.Use(gin.CustomRecovery(func(c *gin.Context, err any) {
userData := auth.GetUserData(c)
admin.NotifyPageFailure(c, err, user)
}))
The only limitation is that a beautiful error message that gin prints is compiles by private methods and is not passed to the callback. If you want the same data you'll probably do some copy/paste