gpt4 book ai didi

go - 何时将 sync.Mutex 与 net/http 和 gorilla/mux 一起使用

转载 作者:行者123 更新时间:2023-12-01 22:43:06 24 4
gpt4 key购买 nike

据我所知,net/http 包使用 goroutines 作为处理程序。有必要用 sync.Mutex 锁定 map 吗?为了防止 nextId 中可能出现的错误函数导致该函数可以计算 map 的旧状态?

这是我的示例代码:

package main

import (
"net/http"
"github.com/gorilla/mux"
"io/ioutil"
"fmt"
)

var testData = map[int]string {
1: "foo",
2: "bar",
}

func main() {
r := mux.NewRouter()
r.HandleFunc("/data", getData).Methods("GET")
r.HandleFunc("/data", addData).Methods("POST")
http.ListenAndServe(":3000", r)
}

func getData(writer http.ResponseWriter, request *http.Request) {
for k, v := range testData {
fmt.Fprintf(writer, "Key: %d\tValue: %v\n", k, v)
}
}

func addData(writer http.ResponseWriter, request *http.Request) {
if data, err := ioutil.ReadAll(request.Body); err == nil {
if len(data) == 0 {
writer.WriteHeader(http.StatusBadRequest)
return
}

id := nextId()
testData[id] = string(data)
url := request.URL.String()
writer.Header().Set("Location", fmt.Sprintf("%s", url))
writer.WriteHeader(http.StatusCreated)

} else {
writer.WriteHeader(http.StatusBadRequest)
}
}

func nextId() int {
id := 1

for k, _ := range testData {
if k >= id {
id = k + 1;
}
}

return id
}

最佳答案

由于标准库的 HTTP 服务器在其自己的 goroutine 上调用处理程序,因此您必须同步访问在处理程序之外定义的所有变量(其中一种访问是写入)。每当您使用 stdlib 的 HTTP 服务器时,您都必须这样做。无论您使用标准库的多路复用器还是 Gorilla 的多路复用器都没有关系。 goroutine 启动发生在多路复用器之外(在调用多路复用器之前)。

如果不这样做(如在您的示例中),则会发生数据竞争,您可以通过使用 -race 运行它来验证它。选项:

WARNING: DATA RACE
Write at 0x00c000090c30 by goroutine 21:
runtime.mapassign_fast64()
/usr/local/go/src/runtime/map_fast64.go:92 +0x0
main.addData()
/home/icza/gows/src/play/play.go:47 +0x191
net/http.HandlerFunc.ServeHTTP()
/usr/local/go/src/net/http/server.go:2007 +0x51
github.com/gorilla/mux.(*Router).ServeHTTP()
/home/icza/gows/pkg/mod/github.com/gorilla/mux@v1.7.3/mux.go:212 +0x13e
net/http.serverHandler.ServeHTTP()
/usr/local/go/src/net/http/server.go:2802 +0xce
net/http.(*conn).serve()
/usr/local/go/src/net/http/server.go:1890 +0x837

Previous read at 0x00c000090c30 by goroutine 7:
runtime.mapiternext()
/usr/local/go/src/runtime/map.go:851 +0x0
main.getData()
/home/icza/gows/src/play/play.go:32 +0x194
net/http.HandlerFunc.ServeHTTP()
/usr/local/go/src/net/http/server.go:2007 +0x51
...

关于go - 何时将 sync.Mutex 与 net/http 和 gorilla/mux 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58766245/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com