2016-12-02 57 views
0

我正在從Node.js轉向Go,我擔心在Node中使用的構造是否可以安全地在Go中執行,以及是否有更通俗的方式來完成相同的事情。我正在使用Echo框架,並且想要設置將在上下文對象中可用的路由特定結構。我可以爲中間件內的每個調用生成結構,但這樣做的代價很高。相反,我在外部func中設置了一次結構,然後返回一個指向外部func中結構的內部func。我的希望是,我只需要花費一次代價,然後在每次調用時都擁有與我的路線相關的正確結構。安全地從內部函數引用外部函數中的值?

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

其中一種慣用的方式是不使用框架https://www.nicolasmerouze.com/build-web-framework-golang/ –

回答

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中的單例模式。

+0

有趣的是,這是我最初的方法。我使用路由方法和路徑作爲查找的關鍵字來存儲附加信息。我決定將其改爲我描述的中間件方法,因爲它看起來「更清潔」,並使數據更接近需要的地方(避免每次查找成本?)。單身模式與中間件模式相比有什麼好處? – AlexGad

+0

我認爲無論使用中間件還是不使用中間件,都可以爲getOperationMap(或其他昂貴的函數)的返回值使用單例實例。我同意在這種情況下使用中間件很好。我不認爲他們是相互排斥的東西。 – philipjkim

1

此代碼安全,不會導致GC問題,並且是Go中可以使用的一種很好的慣用模式。

在您的示例中,只有一個operation將被創建,移動到堆中,然後由每個請求共享,因爲它們由Echo處理。

當我需要初始化處理所有請求時將使用的昂貴結構時,我經常使用這個確切模式。

+0

與philipjkim建議的單例方法相比,您是否看到了這種方法的好處?或者這只是一個偏好問題? – AlexGad

相關問題