go - 我应该在包级别但在 http 处理程序之外声明变量吗?

标签 go httprequest httphandler go-gin

我使用 gin gonic 作为 HTTP 框架,我需要像这样用共享变量对一些路径进行分组:

ur := r.Group("/")
ur.Use(package.Prepare)
{
    ur.GET("/", package.Home)
}

Prepare 处理程序中,我将包变量声明为 package.tplPath 因为我希望所有子路由都可以访问这个变量,而不是在每个 http 处理程序中重写代码。

var tplPath = ""

func Prepare(c *gin.Context) {
    _, filename, _, _ := runtime.Caller(0)
    s := helper.RelativeFilePath(filename)
    tplPath = s[1:len(s)] + "template/"
}

我不知道 Go 如何处理每个进程,以及每个 http 请求的变量。如果在包级别声明了一个变量,它会在每个 http 请求后设置吗?

这被认为是好的做法吗?如果不是,为什么不呢?

最佳答案

这不是线程安全的,包变量在所有 goroutine 之间共享,修改一个例程会更改所有其他例程中的值,从而导致数据竞争。

一般来说;尽可能避免使用包级变量。

编辑:

在 go 中,包是一种模块。对于任何给定的导入路径(基本上是包名称),只存在一个包实例。这意味着在包级别只有 1 个变量实例。

包变量是共享的全局状态。该变量的所有访问器都将访问完全相同的内存。

无论包变量是什么类型,struct/string/int 等。如果它是在包级别定义的,该变量的所有访问器将共享它的同一个实例。

如果(对于 http 服务器)您有并发代码,那么该变量将同时有多个访问器。在某些情况下,这很好,例如仅读取该变量时,但在您的情况下,它似乎会被修改。让这段代码充满活力!

关于go - 我应该在包级别但在 http 处理程序之外声明变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50844390/

相关文章:

c# - 如何从 ASP.NET Core 中的 Request.Body 读取参数

java - android.view.View.requestLayout(View.java :16431)

c# - 从 IHttpHandler(通用处理程序)中的文件路径获取 URL

date - 考虑另一个 TZ 作为引用的服务器时间

go - 无法为 Kubernetes API 类型声明声明种类类型

ssl - 如何为 Go 服务器应用程序设置 Let's Encrypt

asp.net - 通用处理程序没有在 ASP.NET 中被调用

json - 不同类型反射的 Golang JSON 数组 : float64 vs int64

jsf - 如何从 View 范围的 JSF bean 中获取请求参数?

c# - Http无法向服务器发送消息