当前位置: 首页 > 知识库问答 >
问题:

在Golang中使用Http处理程序的全局变量

伊富
2023-03-14

我知道有一些关于这个问题的问题和帖子/文章,但从我的新手角度来看,不完全是这样。问题是,我有一个主程序监听一个端口,并将调用重定向到一个特定的处理程序。典型结构:

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]
}

那么,问题是,我如何在没有所有这些映射作为全局变量的情况下继续这样做?如果它们是结构的一部分,如何从优先级队列函数访问结构?

共有2个答案

漆雕欣德
2023-03-14

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)
}
齐元章
2023-03-14

当处理程序需要变量时,通常意味着您应该实现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