【发布时间】:2019-02-22 21:51:48
【问题描述】:
我需要从 struct 更新值并返回(只读)而不是从 HTTP 处理程序写入,以避免出现竞争条件我正在使用 sync.Mutex 这是一个基本示例:
http://play.golang.org/p/21IimsdKP6e
package main
import (
"encoding/json"
"log"
"net/http"
"sync"
"time"
)
type Counter struct {
count uint
flag bool
mu sync.Mutex
quit chan struct{}
time time.Time
wg sync.WaitGroup
}
func (c *Counter) Start() {
c.count = 1
c.time = time.Now()
c.flag = true
}
func (c *Counter) Listen() {
srv := &http.Server{
Addr: ":8080",
Handler: http.DefaultServeMux,
}
http.HandleFunc("/", c.HandleStatus)
c.wg.Add(1)
go func() {
defer c.wg.Done()
log.Println(srv.ListenAndServe())
}()
go func(quit chan struct{}) {
<-quit
if err := srv.Close(); err != nil {
log.Printf("HTTP error: %v", err)
}
}(c.quit)
}
func (c *Counter) HandleStatus(w http.ResponseWriter, r *http.Request) {
c.mu.Lock()
defer c.mu.Unlock()
status := struct {
Count uint `json:"count"`
Flag bool `json:"flag"`
Time string `json:"time"`
}{
Count: c.count,
Time: c.time.UTC().Format(time.RFC3339),
Flag: c.flag,
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(status); err != nil {
log.Println(err)
}
}
func main() {
c := &Counter{
quit: make(chan struct{}),
}
c.Start()
c.Listen()
timeout := time.After(time.Minute)
for {
select {
case <-time.After(time.Second):
c.mu.Lock()
c.count += 1
c.flag = !c.flag
c.mu.Unlock()
case <-timeout:
close(c.quit)
c.wg.Wait()
return
}
}
}
我有更多的处理程序,但我需要从 Counter struct 读取我需要添加的每个处理程序:
c.mu.Lock()
defer c.mu.Unlock()
在变量被修改的地方,执行如下操作:
c.mu.Lock()
c.count += 1
c.flag = !c.flag
c.mu.Unlock()
因此想知道如何更好地同步/安排代码以防止在每个处理程序上添加Lock/Unlock
【问题讨论】:
标签: go