2017-08-25 20 views
2

私は別のゴルーチンで連続して更新されている多くのフィールドを持つ構造体を持っています(そのうちのいくつかは他の構造体へのポインタでもあります)。同じ構造体は、ページが提供されるときにgoのhttpテンプレートからアクセスされます。Go httpパッケージと共有構造体を提供するには?

コード例:

type SharedStruct struct { 
    Description string 
    Counter int 
    Status_ *Status 
    LastChecked time.Time 
    //other fields 
} 
var shared = &SharedStruct{} 

go func() { 
    //..updates fields every 5 minutes 
}() 

ゴー-HTTPハンドラ:

func someHandler(w http.ResponseWriter, r *http.Request) { 
    t.ExecuteTemplate(w, "page.html", shared) 
} 

page.htmlテンプレート:

... 
Status: {{.Status_.StatusCode}} 
Counter: {{.Counter}} 
Last checked: {{.LastChecked.Format "2006-02-01 15:04:05"}} 

だから、期待通りまでのところすべてが動作しますが、私は承知しています同期がなくても悪いことが起きる可能性があります。これを適切に処理するための好ましい方法は何ですか?

答えて

2

好ましい方法は他の場合と同じです。

どちらの共有構造体が読み込まれたときに、ミューテックスを使用/更新:

var shared = &SharedStruct{} 
var mux = &sync.RWMutex{} 

func someHandler(w http.ResponseWriter, r *http.Request) { 
    mux.RLock() 
    defer mux.RUnlock() 
    t.ExecuteTemplate(w, "page.html", shared) 
} 

// Code that modifies shared: 
mux.Lock() 
shared.Counter++ 
mux.Unlock() 

またはテンプレートの実行に時間がかかる場合、shared構造体のコピーを作成し、時にコピーを渡すためにprotitableかもしれ

テンプレートの実行中に sharedへのアクセスがブロックされないように、テンプレートを実行します。コピーを作成する際には、まだミューテックスを使用する必要があることに注意してください。また、ポインタが、先のとがった値だけでなく変化する可能性がある場合、あなたはまた、それらのコピーを作成する必要があります:テンプレートのみ sharedフィールドの小さなサブセットを使用している場合

func someHandler(w http.ResponseWriter, r *http.Request) { 
    mux.RLock() 
    shared2 := &SharedStruct{} 
    *shared2 = *shared 
    shared2.Status_ = new(Status) 
    *shared2.Status_ = *shared.Status_ 
    mux.RUnlock() 

    t.ExecuteTemplate(w, "page.html", shared2) 
} 

することは、それだけで作るのに十分ですそれらのコースのコピー。

関連する問題