我知道有一些关于这个问题的问题和帖子/文章,但从我的新手角度来看,不完全是这样。问题是,我有一个主程序监听一个端口,并将调用重定向到一个特定的处理程序。典型结构:
func main() {
http.HandleFunc("/something", specificHandler)
http.ListenAndServe(":8080", nil)
}
处理程序类似于:
func specificHandler(w http.ResponseWriter, r *http.Request) {
somepackage.foo()
}
然后,包含函数foo的一些全局变量,基本上是因为函数共享需要它们(例如,当使用容器/堆实现的优先级队列时,它将从全局距离矩阵中获得Swap函数中的优先级当然是可变的)。以及许多其他例子。总之,全局变量...
问题是,正如您可能看到的,这些变量在对处理程序的所有调用中共享。这很糟糕。
我如何才能真正解决这个问题?一定有一种我还没有想到的简单方法,因为它看起来很平常...
提前感谢。
编辑
让它更清楚。例如,在我的A*包中,我有以下全局变量:
var openVerticesAS PriorityQueueAStar
// which vertices are closed
var closedVertices map[int]bool
// which vertices are currently open
var openVertices map[int]bool
// cost from start to node
var gScore map[int]float64
// cost from start to end, passing by node i (g+h)
var fScore map[int]float64
然后,PriorityQueueAStar实现如下:
type PriorityQueueAStar []int // rel id
func (pq PriorityQueueAStar) Len() int { return len(pq) }
func (pq PriorityQueueAStar) Empty() bool { return len(pq) == 0 }
func (pq PriorityQueueAStar) Less(i, j int) bool {
return fScore[pq[i]] < fScore[pq[j]]
}
func (pq PriorityQueueAStar) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}
func (pq *PriorityQueueAStar) Push(x interface{}) {
*pq = append(*pq, x.(int))
}
func (pq *PriorityQueueAStar) Pop() interface{} {
old := *pq
n := len(old)
rel := old[n-1]
*pq = old[0 : n-1]
return rel
}
func (pq PriorityQueueAStar) Top() interface{} {
return pq[0]
}
那么,问题是,我如何在没有所有这些映射作为全局变量的情况下继续这样做?如果它们是结构的一部分,如何从优先级队列函数访问结构?
chowey提到了闭包方法,但有一个警告,它是不可测试或可重用的。如果您有一个返回闭包的函数,那么它实际上是可测试和可重用的。对于某些类型的数据,这可能有助于更清晰的抽象和实现:
func handleThing(thing string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.Write(thing)
}
}
func main() {
http.HandleFunc("/something", handleThing("Hello world!"))
http.ListenAndServe(":8080", nil)
}
当处理程序需要变量时,通常意味着您应该实现handler
接口,而不是提供HandlerFunc
函数。
下面是一个糟糕的示例(使用全局变量):
var globalThing string
func specificHandler(w http.ResponseWriter, r *http.Request) {
w.Write(globalConfigThing)
}
func main() {
globalThing = "Hello world!"
http.HandleFunc("/something", specificHandler)
http.ListenAndServe(":8080", nil)
}
下面是一个更好的示例(不使用全局变量):
type specificHandler struct {
Thing string
}
func (h *specificHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write(h.Thing)
}
func main() {
http.Handle("/something", &specificHandler{Thing: "Hello world!"})
http.ListenAndServe(":8080", nil)
}
如您所见,Handler
可以封装变量。
为了完整,另一种方法是使用函数闭包。这对于一次性处理程序很有效,但是不能重用,并且更难编写单元测试。
func main() {
scopedThing := "Hello world!"
http.HandleFunc("/something", func (w http.ResponseWriter, r *http.Request) {
w.Write(scopedThing)
})
http.ListenAndServe(":8080", nil)
}
如果操作正确,现在可以通过将全局变量作为参数传递等方式避免包somepackage
中的全局变量。
编辑:例如,您可以使用somepackage
包中的几个PriorityQueueAStar
字段定义处理程序结构:
type specificHandler struct {
QueueA somepackage.PriorityQueueAStar
QueueB somepackage.PriorityQueueAStar
QueueC somepackage.PriorityQueueAStar
}
func (h *specificHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.QueueA.Push(h.QueueB.Pop)
h.QueueB.Push(h.QueueC.Pop)
w.Write([]byte("Queues pushed and popped"))
}
我有一个带post请求的控制器。我试图用一个简单的NotNull注释验证POJO。我正在使用ControllerAdvice来处理异常。 所以我尝试使用它,但当我启动应用程序时,我得到了以下信息: 因此,我想为BindException创建自己的处理程序,但当我为BindException类创建ExceptionHandler时,spring应用程序不会启动。如果我注释掉handleBindExc
问题内容: 如何与线程共享全局变量? 我的Python代码示例是: 我不知道如何让两个线程共享一个变量。 问题答案: 您只需要在中声明为global ,这样就无需修改该函数本地的。 在中,您不需要执行任何特殊操作,只要您不尝试修改的值(这将创建一个局部变量以遮盖全局变量;请在需要时使用)>
问题内容: 有没有一种方法可以在Java中创建全局异常处理程序。我想这样使用: 处理程序可能无法捕获在主体中引发的异常。 马丁 问题答案: 使用Thread.setDefaultUncaughtExceptionHandler。有关示例,请参见Rod Hilton的“ Global Exception Handling ”博客文章。
问题内容: 我对Go来说还很陌生,还无法找到任何有关此的信息,也许目前尚无法解决。 我正在尝试删除或替换多路复用器路由(使用http.NewServeMux或大猩猩的mux.Router)。我的最终目标是能够启用/禁用一条路由或一组路由,而不必重新启动程序。 我可能可以在处理程序到处理程序的基础上完成此操作,并且如果该功能被“禁用”,则只返回404,但是我宁愿找到一种更通用的方法来执行此操作,因为
我正在尝试修复VueJS SPA中出现的一种行为,其中出现了一种不稳定状态。应用程序不知道JWT已经过期,因此呈现出用户仍在登录的样子。例如,这可能发生在Hibernate之后。 这些用户可以继续向API发出任何请求,但最终会得到响应(这是正确的)。 我想要一个响应的全局处理程序。(这将是:从vuex清除所有与用户相关的内容,并将页面呈现为用户是访客,并弹出登录表单等。)否则,我将不得不为每个请求
问题内容: 当我的网站是100%jQuery时,我曾经这样做: 为401错误设置全局处理程序。现在,我将angularjs与和一起使用,以向服务器发送(REST)请求。有什么办法可以类似地用角度设置全局错误处理程序吗? 问题答案: 我还在建立一个带有angular的网站,并且遇到了同样的障碍来处理全局401。当我遇到此博客文章时,我最终使用了HTTP拦截器。也许您会发现它和我一样有用。 “基于An