我应该在包级别但在 http 处理程序之外声明变量吗?
Should I declare variables in package level but outside of http handler?
我正在使用 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 服务器)您有并发代码,那么该变量将同时有多个访问器。在某些情况下,这很好,例如仅读取该变量时,但在您的情况下,它似乎会被修改。让这段代码变得活泼!
tplPath是一个全局变量,所有例程都会访问相同的内存地址,并在每次http请求后设置。
如果您只想设置一次,并且 tplPath 不依赖于 http 请求。可以在init函数中设置。
func init(){
_, filename, _, _ := runtime.Caller(0)
s := helper.RelativeFilePath(filename)
tplPath = s[1:len(s)] + "template/"
}
init函数会运行在main之前,只做一次。
我正在使用 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 服务器)您有并发代码,那么该变量将同时有多个访问器。在某些情况下,这很好,例如仅读取该变量时,但在您的情况下,它似乎会被修改。让这段代码变得活泼!
tplPath是一个全局变量,所有例程都会访问相同的内存地址,并在每次http请求后设置。 如果您只想设置一次,并且 tplPath 不依赖于 http 请求。可以在init函数中设置。
func init(){
_, filename, _, _ := runtime.Caller(0)
s := helper.RelativeFilePath(filename)
tplPath = s[1:len(s)] + "template/"
}
init函数会运行在main之前,只做一次。