英文:
Go count dynamic url calls
问题
我正在尝试计算每个新的动态URL的数量:
var count int
// *错误* 非声明语句在函数体外
func increment() error {
count = count + 1
return nil
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
m := make(map[string]int)
if r.Method != "POST" {
http.Error(w, "不支持的方法。", http.StatusNotFound)
return
}
increment()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
urlPath := r.RequestURI
value, ok := m[urlPath]
if ok {
m[urlPath] = count + 1
fmt.Println("value: ", value)
} else {
m[urlPath] = count
fmt.Println(m)
fmt.Println("未找到键")
}
fmt.Println(m)
fmt.Fprintf(w, "Hello!", count)
fmt.Printf("%s", b)
}
func main() {
http.HandleFunc("/report/", helloHandler) // 更新此行代码
fmt.Printf("在端口8080上启动服务器\n")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
结果应该是一个包含所有URL作为键和次数作为值的映射,例如:
{"abc": 2, "foo": 1, "ho": 5}
但是当我运行我的代码时,每次键都会被更新一次。
英文:
I am trying to count each new dynamic URL
var count int
// *Error* non-declaration statement outside function body
func increment() error {
count = count + 1
return nil
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
m := make(map[string]int)
if r.Method != "POST" {
http.Error(w, "Method is not supported.", http.StatusNotFound)
return
}
increment()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
urlPath := r.RequestURI
value, ok := m[urlPath]
if ok {
m[urlPath] = count + 1
fmt.Println("value: ", value)
} else {
m[urlPath] = count
fmt.Println(m)
fmt.Println("key not found")
}
fmt.Println(m)
fmt.Fprintf(w, "Hello!", count)
fmt.Printf("%s", b)
}
func main() {
http.HandleFunc("/report/", helloHandler) // Update this line of code
fmt.Printf("Starting server at port 8080\n")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
the result should be map with all URLs as a key and number of times as value such:
{"abc" : 2
"foo" : 1
"ho": 5}
but when i run my code evry time the key updated again an agin
答案1
得分: 2
有多个问题:
-
每次执行处理程序函数时都会创建一个新的映射。
-
由于HTTP处理程序在并发运行的单独goroutine上执行,全局变量
counter
存在数据竞争。
我不确定我是否正确解析了你的意思,但是你应该:
- 有一个全局映射。
- 每次访问该映射时都要使用互斥锁进行保护。
- 递增映射中的计数器值。
类似这样的代码:
var (
hitsMu sync.Mutex
hits = make(map[string]*int)
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// ...
hitsMu.Lock()
defer hitsMu.Unlock()
counterPtr := hits[urlPath]
if counterPtr == nil {
counterPtr = new(int)
hits[urlPath] = counterPtr
}
*counterPtr += 1
// ...
}
英文:
There are multiple problems:
-
You create a new map on each execution of your handler function.
-
As HTTP handlers execute on separate goroutines which are running concurrently, you have a data race on the global
counter
variable.
I'm not really sure I have correctly parsed what you're after, but supposedly you should:
- Have a global map.
- Have each access to that map protected by a mutex.
- Increment counters which are values in the map.
Something like this:
var (
hitsMu sync.Mutex
hits = make(map[string]*int)
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// ...
hitsMu.Lock()
defer hitsMu.Unlock()
counterPtr := hits[urlPath]
if counterPtr == nil {
counterPtr = new(int)
hits[urlPath] = counterPtr
}
*counterPtr += 1
// ...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论