Golang中访问计数Cookie为何会同时计数两次
Golang中访问计数Cookie为何会同时计数两次
我正在学习Web开发和Cookie。
在我的代码中,当访问 localhost:8084/abc 时,用于统计访问次数的Cookie工作正常。
它会逐一累加访问次数。
但是,当我访问默认路径("/")时,Cookie会同时将访问次数计数两次。
有人知道这个问题以及如何解决吗?
package main
import (
"fmt"
"net/http"
"strconv"
"text/template"
)
func main() {
http.HandleFunc("/", ab)
http.HandleFunc("/abc", abc)
http.ListenAndServe(":8084", nil)
}
func abc(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie("VisitNum")
if err != nil {
fmt.Fprint(w, err, " 1")
}
tpl, err := template.ParseFiles("index2.html")
if err != nil {
fmt.Fprint(w, err, " 2")
}
tpl.Execute(w, c.Value)
}
func ab(w http.ResponseWriter, r *http.Request) {
c, _ := r.Cookie("VisitNum")
if c == nil {
c := &http.Cookie{
Name: "VisitNum",
Value: "1",
}
http.SetCookie(w, c)
} else {
cin, err := strconv.Atoi(c.Value)
if err != nil {
fmt.Fprint(w, err, " 4")
}
cin++
c.Value = strconv.Itoa(cin)
http.SetCookie(w, c)
}
tpl, _ := template.ParseFiles("index.html")
tpl.Execute(w, "aaa")
}
更多关于Golang中访问计数Cookie为何会同时计数两次的实战教程也可以访问 https://www.itying.com/category-94-b0.html
检查请求的 Method。你可能收到了除 GET 之外的其他请求。
更多关于Golang中访问计数Cookie为何会同时计数两次的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
处理路径“/”会被视为一个目录,并将处理所有未被其他处理程序匹配的请求。就像处理“/api/”也会处理对“/api/foobar”的请求一样。
如果你打开浏览器的开发者工具和网络标签页,你将看到所有发往你服务器的请求。大多数浏览器会搜索网站图标(即浏览器标签页上每个页面不同的小图标),并在后台静默调用“/favicon.ico”。这个调用会被你的“/”处理程序接收。
你可以通过在处理程序中添加 fmt.Printf("%+v\n", r) 来调试这个问题,占位符“%+v”会打印请求对象的所有详细信息,你可以看到被调用的路径是什么。
fmt.Printf("%+v\n", r)
这个问题是由于浏览器对默认路径"/"的请求行为导致的。当访问根路径时,浏览器通常会同时请求/favicon.ico,导致处理函数被调用两次。
以下是修改后的代码,通过检查请求路径来避免重复计数:
package main
import (
"fmt"
"net/http"
"strconv"
"text/template"
)
func main() {
http.HandleFunc("/", ab)
http.HandleFunc("/abc", abc)
http.ListenAndServe(":8084", nil)
}
func abc(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie("VisitNum")
if err != nil {
fmt.Fprint(w, err, " 1")
}
tpl, err := template.ParseFiles("index2.html")
if err != nil {
fmt.Fprint(w, err, " 2")
}
tpl.Execute(w, c.Value)
}
func ab(w http.ResponseWriter, r *http.Request) {
// 忽略对favicon.ico的请求
if r.URL.Path == "/favicon.ico" {
return
}
c, _ := r.Cookie("VisitNum")
if c == nil {
c := &http.Cookie{
Name: "VisitNum",
Value: "1",
}
http.SetCookie(w, c)
} else {
cin, err := strconv.Atoi(c.Value)
if err != nil {
fmt.Fprint(w, err, " 4")
}
cin++
c.Value = strconv.Itoa(cin)
http.SetCookie(w, c)
}
tpl, _ := template.ParseFiles("index.html")
tpl.Execute(w, "aaa")
}
另一种更通用的解决方案是使用中间件来统计访问次数,避免路径相关的重复计数:
package main
import (
"fmt"
"net/http"
"strconv"
"text/template"
)
func main() {
http.HandleFunc("/", ab)
http.HandleFunc("/abc", abc)
http.ListenAndServe(":8084", nil)
}
func abc(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie("VisitNum")
if err != nil {
fmt.Fprint(w, err, " 1")
}
tpl, err := template.ParseFiles("index2.html")
if err != nil {
fmt.Fprint(w, err, " 2")
}
tpl.Execute(w, c.Value)
}
func ab(w http.ResponseWriter, r *http.Request) {
// 只在处理主页面请求时计数
if r.URL.Path == "/" {
c, _ := r.Cookie("VisitNum")
if c == nil {
c := &http.Cookie{
Name: "VisitNum",
Value: "1",
}
http.SetCookie(w, c)
} else {
cin, err := strconv.Atoi(c.Value)
if err != nil {
fmt.Fprint(w, err, " 4")
}
cin++
c.Value = strconv.Itoa(cin)
http.SetCookie(w, c)
}
}
tpl, _ := template.ParseFiles("index.html")
tpl.Execute(w, "aaa")
}
还可以使用请求方法过滤来避免OPTIONS预检请求导致的重复计数:
func ab(w http.ResponseWriter, r *http.Request) {
// 只统计GET请求
if r.Method != http.MethodGet {
return
}
// 忽略对favicon.ico的请求
if r.URL.Path == "/favicon.ico" {
return
}
c, _ := r.Cookie("VisitNum")
if c == nil {
c := &http.Cookie{
Name: "VisitNum",
Value: "1",
}
http.SetCookie(w, c)
} else {
cin, err := strconv.Atoi(c.Value)
if err != nil {
fmt.Fprint(w, err, " 4")
}
cin++
c.Value = strconv.Itoa(cin)
http.SetCookie(w, c)
}
tpl, _ := template.ParseFiles("index.html")
tpl.Execute(w, "aaa")
}

