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

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

问题描述

我试图学习Go web编程,这里是一个简单的web服务器:它打印出被调用的时间。

  b 

$ b $ f







// HelloWorld打印被调用的时间。
func HelloWorld(w http.ResponseWriter,r * http.Request){
calls ++
fmt.Fprintf(w,你叫我%d次,调用)


func main(){
fmt.Printf(在http://localhost%v.\\\
启动服务器,5000)
http.HandleFunc /,HelloWorld)
http.ListenAndServe(:5000,nil)
}

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

 您已经给我打了1次
You给我打了3次
你给我打了5次
....


$ b $问题:为什么它是1,3,5次,而不是1,2,3 ...?什么是函数 HelloWorld 被调用的顺序?

解决方案

因为每个传入的请求都被路由到您的 HelloWorld()处理函数中,并且浏览器在引擎下进行多个调用,特别是 /favicon.ico



由于您的网络服务器不会发回有效的图标,因此当您在浏览器中刷新页面时,它会再次请求它。 / p>

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

 名称状态类型
-------- ------------------------------------------------
localhost 200文件
favicon.ico 200 text / plain

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

另外请注意,多个goroutines可以同时处理请求,所以你的解决方案有一场竞赛。您应该同步访问调用变量,或使用 sync / atomic 包安全地增加计数器,例如:

  var calls int64 

func HelloWorld(w http.ResponseWriter,r * http.Request){
count:= atomic.AddInt64(& calls,1)
fmt.Fprintf(w,你叫我%d次,count)
}

一个简单的修复来实现你想要的是检查请求路径,如果它不是根/,那么不要增量,例如:

  func HelloWorld(w http.ResponseWriter,r * http.Request){
if r。 URL.Path!=/{
return
}
count:= atomic.AddInt64(& calls,1)
fmt.Fprintf(w,You've称为%d次,计数)
}

您也可以选择仅排除请求 favicon.ico

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


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.\n", 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
....

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

解决方案

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.

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

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.

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

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

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

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

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