2016-12-02 7 views
0

私はNode.jsからGoに移動します。ノードで使用する構造体がGoで安全であるかどうか、同じことを達成するためにもっと慣用的な方法があるかどうかについては懸念しています。私はEchoフレームワークを使用しており、コンテキストオブジェクト内で使用できるルート固有の構造体を設定したいと考えています。私はミドルウェア内のすべての呼び出しのための構造体を生成することができますが、それを行うには高価です。代わりに、構造体を外側のfuncに1回セットし、外側の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

慣用的な方法の1つは、フレームワークを使用していない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を実行することができます。

Goのシングルトンパターンを理解するためにhttp://marcio.io/2015/07/singleton-pattern-in-go/をお勧めします。

+0

興味深いことに、これは私の最初のアプローチでした。ルックアップのキーとしてルートメソッドとパスを使用して追加情報を保存しました。私はそれを「よりきれいな」ように見せ、必要な場所にデータを近づけたので(これは毎回ルックアップのコストを避けています)、私が記述したミドルウェアのアプローチに変更することにしました。シングルトンアプローチとミドルウェアアプローチの利点はありますか? – AlexGad

+0

ミドルウェアを使用するかどうかに関わらず、getOperationMap(または他の高価な関数)の戻り値にシングルトンインスタンスを使用するのは良いパターンだと思います。そして、私はこの状況でミドルウェアを使用することがうまくいくことに同意します。私は彼らが相互に排他的な(または対の)ものではないと思います。 – philipjkim

1

このコードは安全でGCに問題はなく、Goで使用できる良い慣用パターンです。

この例では、operationが1つだけ作成され、ヒープに移動され、Echoで処理されるごとに要求ごとに共有されます。

すべてのリクエストを処理する際に使用される高価な構造体を初期化する必要がある場合は、このパターンを自分で使用することがよくあります。

+0

philipjkimが示唆しているシングルトンアプローチと比較して、このアプローチのメリットはありますか?それとも本当に好みの問題ですか? – AlexGad

関連する問題