为什么这个简单的 Web 服务器被称为偶数次? [英] Why this simple web server is called even number times?

查看:29
本文介绍了为什么这个简单的 Web 服务器被称为偶数次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 Go 网络编程,这里有一个简单的网络服务器:它打印出被调用的时间.

I'm trying to learn Go web programming, and here is a simple web server: it prints out the times being called.

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.
", 5000)
  http.HandleFunc("/", HelloWorld)
  http.ListenAndServe(":5000", nil)
}

当我刷新页面时,我得到:

When I refresh the page, I got:

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 函数的调用顺序是什么?

Question: Why it is 1, 3, 5 times, rather than 1,2,3...? What's the order of the function HelloWorld being called?

推荐答案

这是因为每个传入的请求都会路由到您的 HelloWorld() 处理程序函数,并且浏览器会在后台进行多次调用,专门针对 /favicon.ico.

It is because every incoming request is routed to your HelloWorld() handler function, and the browser makes multiple calls under the hood, specifically to /favicon.ico.

由于您的网络服务器没有发回有效的图标,当您在浏览器中刷新页面时,它会再次请求它.

And since your web server does not send back a valid favicon, it will request it again when you refresh the page in the browser.

使用 Chrome 试试:打开开发者工具 (CTRL+SHIFT+I),然后选择网络"选项卡.点击刷新,您将看到 2 个新条目:

Try it with Chrome: open the Developer tools (CTRL+SHIFT+I), and choose the "Network" tab. Hit refresh, and you will see 2 new entries:

Name          Status   Type
--------------------------------------------------------
localhost     200      document
favicon.ico   200      text/plain

由于您的计数器以 0 开头(int 类型的默认值),您将其递增一次并返回 1.然后对 favicon.ico 的请求再次增加它(2),但结果没有显示.然后,如果您刷新,它会再次增加到 3,然后您将其发回,等等.

Since your counter starts with 0 (default value for type int), you increment it once and you send back 1. Then the request for favicon.ico increments it again (2), but the result is not displayed. Then if you refresh, it gets incremented again to 3 and you send that back, etc.

另请注意,多个 goroutine 可以同时处理请求,因此您的解决方案存在竞争.您应该同步对 calls 变量的访问,或使用 sync/atomic 包以安全地递增计数器,例如:

Also note that multiple goroutines can serve requests concurrently, so your solution has a race. You should synchronize access to the calls variable, or use the sync/atomic package to increment the counter safely, for example:

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)
}

实现您想要的简单修复"是检查请求路径,如果它不是根"/",则不要增加,例如:

A simple "fix" to achieve what you want would be to check the request path, and if it is not the root "/", don't increment, e.g.:

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 的请求,例如:

You may also choose to only exclude requests for favicon.ico, e.g.:

if r.URL.Path == "/favicon.ico" {
    return
}

这篇关于为什么这个简单的 Web 服务器被称为偶数次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆