dongqing5925 2017-08-25 09:05
浏览 31
已采纳

如何使用Go http包提供共享结构?

I have a struct with many fields (some of them are pointers to other structs as well) which are being continuosly updated in a separate goroutine. The same struct is accessed from go's http template when a page is served.

Code example:

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

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

go-http handler:

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

and page.html template:

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

So far everything works as expected, but I'm aware that bad things can happen without any synchronization. What is the preferred way to handle this properly?

  • 写回答

1条回答 默认 最新

  • dry18813 2017-08-25 09:15
    关注

    The preferred way is the same as in any other cases.

    Either use a mutex when the shared struct is read / updated:

    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()
    

    Or if the template execution takes long time, it may be protitable to make a copy of the shared struct and pass the copy when executing the template, so that during template execution access to shared is not blocked. Note that while making the copy you still have to use a mutex. Also if not only the pointers but the pointed values may change, you also have to make a copy of those:

    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)
    }
    

    If the template only uses a small subset of the shared fields, it is enough to make only a copy of those of course.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码