英文:
HandleFunc being called twice
问题
我正在使用Go语言遵循一个简单的Web服务器示例。
我插入了一个log
语句,所以最终的代码如下所示:
package main
import (
"io"
"log"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
log.Println("hello.")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", hello)
http.ListenAndServe(":8000", mux)
}
问题是,每当我在Web浏览器中加载端口8000时,这个函数会被调用两次。这是一个问题,因为我打算在每次访问页面时递增一个计数器。由于这种行为,计数器会被递增两次。另一方面,如果我使用curl localhost:8000
命令,它只会被调用一次。
我觉得我在这里漏掉了一些非常愚蠢的东西。
英文:
I am following a simple web server example in Go.
I inserted a log
statement so that the resulting code looks like below:
package main
import (
"io"
"log"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello world!")
log.Println("hello.")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", hello)
http.ListenAndServe(":8000", mux)
}
Problem is that whenever I load port 8000 in my web browser, this function is called twice. This is an issue because I intend to increment a counter on each page visit. With this behavior, counter gets incremented twice. OTOH, if I do curl localhost:8000
, it is called only once.
I feel it's something really silly that I am missing here.
答案1
得分: 41
只需记录请求即可。您会发现您的浏览器也会请求 /favicon.ico。
有关更多信息,请参阅 https://en.wikipedia.org/wiki/Favicon。
英文:
Just log the requests. You will realize that your browser also requests /favicon.ico.
See https://en.wikipedia.org/wiki/Favicon for more information.
答案2
得分: 21
如果您是从服务中发出请求,那么没问题,但如果您是从浏览器进行测试,并且不是为了生产意图,您可以在Golang代码中执行以下操作以避免浏览器加载favicon:
http.HandleFunc("/favicon.ico", doNothing)
func doNothing(w http.ResponseWriter, r *http.Request){}
对于投票给负面的人:这是有效的,抱歉在不需要favicon或其他内容的API中使用这段代码...
英文:
If you request from a service is fine, but if you test from a browser and is not the production intention you can do this in golang code for avoid browser load the favicon:
http.HandleFunc("/favicon.ico", doNothing)
And the function
func doNothing(w http.ResponseWriter, r *http.Request){}
For people voting negatives: this works, sorry for handle it with this code in an api that doesn't need favicon or whatever...
答案3
得分: 3
根据Didier的说法,这是你的浏览器尝试加载网站图标。你可以通过将以下代码添加到
标签中来阻止这种情况发生:<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
英文:
As Didier says, it's your browser trying to load the favicon. You can prevent this by adding this code to the <head>:
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
答案4
得分: 3
根据Didier Spezia所说,"/"
是一个子树路径的示例(因为它以斜杠结尾)。另一个示例可能是"/static/"
。当请求的URL路径的开头与子树路径匹配时,子树路径模式将被匹配(并调用相应的处理程序)。如果有助于你的理解,你可以将子树路径视为在末尾有一个通配符,类似于"/**"
或"/static/**"
。这解释了为什么"/"
模式充当了一个捕获所有的作用。该模式实际上意味着匹配一个斜杠,后面跟着任何内容(或根本没有内容)。
为了防止这种情况发生,只需在你的hello处理程序中添加一个检查,如下所示:
func hello(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
io.WriteString(w, "Hello world!")
log.Println("hello.")
}
英文:
Building on what Didier Spezia said,
"/"
is an example of a subtree path (because it ends in a trailing
slash). Another example would be something like "/static/"
. Subtree path patterns are
matched (and the corresponding handler called) whenever the start of a request URL path
matches the subtree path. If it helps your understanding, you can think of subtree paths as
acting a bit like they have a wildcard at the end, like "/**"
or "/static/**" .
This helps explain why the "/"
pattern is acting as a catch-all. The pattern essentially
means match a single slash, followed by anything (or nothing at all).
To prevent that from happening,
just add a check in your hello handler like so
func hello(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
io.WriteString(w, "Hello world!")
log.Println("hello.")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论