2016-02-22 7 views
9

Sto cercando di imparare Vai alla programmazione web, ed ecco un semplice server web: stampa i tempi chiamati.Perché questo semplice web server è chiamato anche numero di volte?

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

Quando ho aggiornare la pagina, ho ottenuto:

You've called me 1 times 
You've called me 3 times 
You've called me 5 times 
.... 

Domanda: Perché è 1, 3, 5 volte, piuttosto che 1,2,3 ...? Qual è l'ordine della funzione HelloWorld chiamata?

+2

stampa la richiesta uri per vedere ulteriori richieste inviate dal tuo browser. – dit

risposta

11

E 'perché ogni richiesta in arrivo viene indirizzata alla funzione del gestore HelloWorld(), e il browser rende più chiamate sotto il cofano, in particolare per /favicon.ico.

E poiché il tuo server web non restituisce una favicon valida, lo richiederà di nuovo quando aggiorni la pagina nel browser.

Provalo con Chrome: apri gli strumenti di sviluppo (CTRL + MAIUSC + I) e seleziona la scheda "Rete". Hit di aggiornamento, e vedrete 2 nuove voci:

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

Dal momento che il contatore inizia con 0 (valore di default per il tipo int), si incrementa una volta e si invia indietro 1. Quindi la richiesta di favicon.ico lo incrementa nuovamente (2), ma il risultato non viene visualizzato. Quindi, se si aggiorna, viene nuovamente incrementato a 3 e lo si invia nuovamente, ecc.

Si noti inoltre che più goroutine possono servire richieste contemporaneamente, quindi la vostra soluzione ha una corsa. Si dovrebbe sincronizzare l'accesso alla variabile calls, o utilizzare il pacchetto sync/atomic per incrementare il contatore in modo sicuro, per esempio:

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

Un semplice "fix" per ottenere ciò che si desidera sarebbe quello di verificare il percorso di richiesta, e se non è la radice "/", non incrementare, ad esempio:

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

si può anche scegliere di escludere solo le richieste per favicon.ico, ad esempio:

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