我正在从Node.js转到Go,我担心我在Node中使用的构造在Go中是否安全,以及是否有更惯用的方法来完成同样的事情。我正在使用Echo框架,并希望设置一个特定于路由的结构,该结构将在上下文对象中可用。我可以为中间件中的每个调用生成结构,但这样做很昂贵。相反,我在外部函数中设置一次结构,然后返回一个内部函数,该函数引用外部函数中的结构。我的希望是,我只需要产生一次发电成本,然后为每次通话都有与我的路线相关的正确结构。
e.POST(path, POST.GenericPostHandler, func(next echo.HandlerFunc) echo.HandlerFunc {
operation := getOperationMap(path)
return func(c echo.Context) error {
c.Set("op", operation)
return next(c)
}
})
此代码是否有任何问题?它会导致GC出现问题吗?有没有更有效的方法来完成同样的事情?我假设每次调用中间件时都会生成结构的副本。
答案 0 :(得分:1)
此代码是安全的,不会导致GC问题,并且是可以在Go中使用的良好的惯用模式。
在您的示例中,只有一个operation
将被创建,移动到堆中,然后在每个请求由Echo处理时共享。
当我需要初始化一个在处理所有请求时将使用的昂贵结构时,我经常自己使用这个模型。
答案 1 :(得分:0)
如果operationMap
在初始化后永远不会更改,您可以将operationMap
声明为单例实例,如下所示:
package main
import (
"fmt"
"sync"
)
var (
operationMapInst map[string]string // I don't know the exact type of map, so you should change the type.
operationMapOnce sync.Once
)
func getOperationMap() map[string]string {
// operationMapOnce.Do() runs only once
// when the first time getOperationMap() is called.
operationMapOnce.Do(func() {
// Initialize operationMapInst.
operationMapInst = map[string]string{"/": "root", "/ver": "version"}
fmt.Println("operaionMap has initialized!")
})
return operationMapInst
}
func main() {
// The initialization logic runs only once.
// Because getOperationMap() returns map,
// syntax for the value for a path should be getOperationMap()[path],
// not getOperationMap(path).
rootOp, ok := getOperationMap()["/"]
fmt.Println(rootOp, ok)
// repetition
rootOp, ok = getOperationMap()["/"]
fmt.Println(rootOp, ok)
verOp, ok := getOperationMap()["/ver"]
fmt.Println(verOp, ok)
verOp, ok = getOperationMap()["/ver"]
fmt.Println(verOp, ok)
}
您可以运行此代码here。
我建议http://marcio.io/2015/07/singleton-pattern-in-go/了解Go中的单身模式。