我的Go Web应用程序中有一个相当快捷的错误处理程序,它会引发HTTP错误,记录响应的重要部分并提供错误模板。我想删除在处理程序中多次编写类似代码的重复:
err := doSomething()
if err != nil {
serverError(w, r, err, code)
}
我已经阅读了Error Handling and Go文章,其中定义了一个自定义HTTP处理程序类型,该类型将返回这样的错误类型/结构(甚至返回int,err):
type appHandler func(http.ResponseWriter, *http.Request) *appError
type appError struct {
code int
Err error
}
// Ensures appHandler satisfies the http.Handler interface
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
switch err.Code {
case http.StatusNotFound:
http.NotFound(w, r)
case http.StatusInternalServerError:
http.Error(w, "message", http.StatusInternalServerError)
default:
http.Error(w, "message", err.Code)
}
}
}
但是我不确定如何保留现有的中间件功能/包装,使我可以像这样链接中间件:r.HandleFunc("/route", use(myHandler, middleware1, middleware2))
where use
和我的中间件看起来像这样:
func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
for _, m := range middleware {
h = m(h)
}
return h
}
func AntiCSRF(h http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do something
// h.ServeHTTP(w,r)
}
}
据我所知,它会像下面这样(不起作用)。我说错了cannot use m(h) (type http.Handler) as type appHandler in assignment: need type assertion
。我如何解决这个问题,同时又保持中间件本身“不变”?
您可以在此处找到一个(简化的)游乐场示例:http :
//play.golang.org/p/Cmmo-wK2Af
r.Handle("/route", use(myHandler, middleware.NoCache)) // Contrived example!
func use(h myHandlerType?, middleware ...func(http.Handler) http.Handler) http.Handler {
for _, m := range middleware {
h = m(h)
}
return h
}
func myHandler(w http.ResponseWriter, r *http.Request) *appError {
// Extremely contrived example
name := "Matt"
_, err := fmt.Fprintf(w, "Hi %s", name)
if err != nil {
return &appError{500, err}
}
return nil
}
func contrivedMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=0, private, must-revalidate")
w.Header().Set("X-Accel-Expires", "0")
h.ServeHTTP(w, r)
})
}
我缺少什么,还有更好的方法吗?
感谢#go-nuts上的“
cronos”帮助,我设法解决了这一问题。
该解决方案允许我使用自定义处理程序类型,链中间件,并避免重复包装处理程序(即appHandler(myHandler),中间件…):
type appHandler func(http.ResponseWriter, *http.Request) *appError
type appError struct {
Code int
Error error
}
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if e := fn(w, r); e != nil {
switch e.Code {
case http.StatusNotFound:
notFound(w, r)
case http.StatusInternalServerError:
serverError(w, r, e.Error, e.Code)
default:
serverError(w, r, e.Error, e.Code)
}
}
}
func use(h appHandler, middleware ...func(http.Handler) http.Handler) http.Handler {
var res http.Handler = h
for _, m := range middleware {
res = m(res)
}
return res
}
func someMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=0, private, must-revalidate")
w.Header().Set("X-Accel-Expires", "0")
h.ServeHTTP(w, r)
})
}
func myHandler(w http.ResponseWriter, r *http.Request) *appError {
err := doSomething()
if err != nil {
return &appError{500, err}
}
// render your template, etc.
return nil
}
路线如下所示: r.Handle("/route", use(myHandler, someMiddleware))
您显然可以进行修改appHandler
以返回所需的内容,并向其添加其他字段appError
等等。如果要将路由器应用于所有路由,则中间件也可以包装路由器-即http.Handle("/", someMiddleware(r))
很多批处理问题都可以通过单进程、单线程的工作模式来完成, 所以在想要做一个复杂设计和实现之前,请审查你是否真的需要那些超级复杂的实现。 衡量实际作业(job)的性能,看看最简单的实现是否能满足需求: 即便是最普通的硬件,也可以在一分钟内读写上百MB数据文件。 当你准备使用并行处理技术来实现批处理作业时,Spring Batch提供一系列选择,本章将对他们进行讲述,虽然某些功能不在本章中涵盖。从高层
4.1扩展断点处理 在前面的章节中我们讲解了用事件处理函数处理调试事件的方法。用 PyDbg 可以很容 易的扩展这种功能,只需要构建一个用户模式的回调函数。当收到一个调试事件的时候,回 调函数执行我们定义的操作。比如读取特定地址的数据,设置更更多的断点,操作内存。操 作完成后,再将权限交还给调试器,恢复被调试的进程。 PyDbg 设置函数的断点原型如下: bp_set(address, descr
使用远程分块的Step被拆分成多个进程进行处理,多个进程间通过中间件实现通信. 下面是一幅模型示意图: Master组件是单个进程,从属组件(Slaves)一般是多个远程进程。如果Master进程不是瓶颈的话,那么这种模式的效果几乎是最好的,因此应该在处理数据比读取数据消耗更多时间的情况下使用(实际应用中常常是这种情形)。 Master组件只是Spring Batch Step 的一个实现, 只是
启动并行处理最简单的方式就是在 Step 配置中加上一个TaskExecutor , 比如,作为 tasklet 的一个属性: <step id="loading"> <tasklet task-executor="taskExecutor">...</tasklet> </step> 上面的示例中, taskExecutor指向了另一个实现 TaskExecutor 接口的Bean. T
在许多函数中,我们都有一个签名,比如,但是我们不能将Future传递给这个函数,对吗?
问题内容: 我已从提供回调来跟踪提交给的任务的执行。 现在,我看到的是任务是否已提交,但最终进入队列,并且任务仍被调用(方法仍然被调用),并且(可能)检查任务已取消且未调用包装的可调用对象。 我应该做例如 还是应该打电话给我?在检查取消和对其进行任何操作之间,这两种方法似乎都容易受到比赛条件的影响。 问题答案: 您说对了,那是对的。系统 最多 会调用 一次 ,因此如果任务在通过运行之前已被取消,您