为啥这个简单的 Web 服务器会被调用偶数次?
Posted
技术标签:
【中文标题】为啥这个简单的 Web 服务器会被调用偶数次?【英文标题】:Why this simple web server is called even number times?为什么这个简单的 Web 服务器会被调用偶数次? 【发布时间】:2016-06-03 16:12:52 【问题描述】:我正在尝试学习 Go 网络编程,这是一个简单的网络服务器:它打印出被调用的时间。
package main
import (
"fmt"
"net/http"
)
var calls int
// HelloWorld print the times being called.
func HelloWorld(w http.ResponseWriter, r *http.Request)
calls++
fmt.Fprintf(w, "You've called me %d times", calls)
func main()
fmt.Printf("Started server at http://localhost%v.\n", 5000)
http.HandleFunc("/", HelloWorld)
http.ListenAndServe(":5000", nil)
当我刷新页面时,我得到:
You've called me 1 times
You've called me 3 times
You've called me 5 times
....
问题:为什么是1、3、5次,而不是1、2、3...?函数HelloWorld
被调用的顺序是什么?
【问题讨论】:
打印请求 uri 以查看从您的浏览器发送的其他请求。 HandleFunc being called twice的可能重复 【参考方案1】:这是因为每个传入的请求都会路由到您的 HelloWorld()
处理函数,并且浏览器会在后台进行多次调用,特别是对 /favicon.ico
。
由于您的网络服务器没有发回有效的网站图标,当您在浏览器中刷新页面时,它会再次请求它。
用 Chrome 试试:打开开发者工具 (CTRL+SHIFT+I),然后选择“网络”选项卡。点击刷新,您将看到 2 个新条目:
Name Status Type
--------------------------------------------------------
localhost 200 document
favicon.ico 200 text/plain
由于您的计数器以0
(int
类型的默认值)开头,因此您将其递增一次并返回1
。然后favicon.ico
的请求再次增加它(2
),但结果不显示。然后,如果您刷新,它会再次递增到 3
,然后您将其发回,等等。
另外请注意,多个 goroutine 可以同时处理请求,因此您的解决方案存在竞争。您应该同步对calls
变量的访问,或者使用sync/atomic
包来安全地递增计数器,例如:
var calls int64
func HelloWorld(w http.ResponseWriter, r *http.Request)
count := atomic.AddInt64(&calls, 1)
fmt.Fprintf(w, "You've called me %d times", count)
实现您想要的一个简单“修复”是检查请求路径,如果它不是根"/"
,请不要增加,例如:
func HelloWorld(w http.ResponseWriter, r *http.Request)
if r.URL.Path != "/"
return
count := atomic.AddInt64(&calls, 1)
fmt.Fprintf(w, "You've called me %d times", count)
您也可以选择仅排除对favicon.ico
的请求,例如:
if r.URL.Path == "/favicon.ico"
return
【讨论】:
以上是关于为啥这个简单的 Web 服务器会被调用偶数次?的主要内容,如果未能解决你的问题,请参考以下文章