如何在golang http服务器中定义全局计数器

时间:2015-01-13 08:27:03

标签: http go

我是GoLang的新手  想要在go-lang中定义一个全局计数器来记录对http服务器进行了多少次查询。

我认为最简单的方法是定义一个全球性的'存储当前计数的变量,并在每个查询中增加它(为方便起见,请将并发问题放在一边)。

无论如何,这是我计划到目前为止实现此目的的代码:

package main

import (
    "fmt"
    "net/http"
)

count := 0 // *Error* non-declaration statement outside function body
func increment() error{
    count = count + 1
    return nil
}

func mainHandler(w http.ResponseWriter, r *http.Request){
    increment()
    fmt.Fprint(w,count)
}

func main(){
    http.HandleFunc("/", mainHandler)
    http.ListenAndServe(":8085",nil)
}

如您所见,var count无法在那里定义,它与我以前使用的Java servlet不同。

那我怎么能实现这个目标呢?

4 个答案:

答案 0 :(得分:3)

在函数之外,您不能使用短变量声明:=。在定义全局变量的函数之外,您必须使用variable declaration(使用var关键字):

var count int

它会自动初始化为int的零值0

<强>链接:

我建议您阅读Go Language Specification的相关部分:

Variable declarations

Short variable declarations

注意:

由于每个请求的处理都在其自己的goroutine中运行,因此您需要显式同步来访问共享计数器,或者您必须使用其他同步方法来进行正确的计数。

答案 1 :(得分:3)

您可能希望在expvar包中的golang中使用标准方式 例如http://go-wise.blogspot.com/2011/10/expvar.html

package main

import (
    "expvar"
    "fmt"
    "http"
    "io"
)

// Two metrics, these are exposed by "magic" :)
// Number of calls to our server.
var numCalls = expvar.NewInt("num_calls")
// Last user.
var lastUser = expvar.NewString("last_user")

func HelloServer(w http.ResponseWriter, req *http.Request) {
    user := req.FormValue("user")

    // Update metrics
    numCalls.Add(1)
    lastUser.Set(user)

    msg := fmt.Sprintf("G'day %s\n", user)
    io.WriteString(w, msg)
}

func main() {
    http.HandleFunc("/", HelloServer)
    http.ListenAndServe(":8080", nil)
}

答案 2 :(得分:0)

请注意,您可能需要考虑使用sync包,因为counter = counter + 1会在同时调用时跳过一个。

答案 3 :(得分:0)

该计数器必须自动进行递增计数,否则您将出现比赛条件并错过一些计数。

声明一个全局int64变量,并使用sync.atomic方法访问它:

package main

import (
    "net/http"
    "sync/atomic"
)

var requests int64 = 0

// increments the number of requests and returns the new value
func incRequests() int64 {
    return atomic.AddInt64(&requests, 1)
}

// returns the current value
func getRequests() int64 {
    return atomic.LoadInt64(&requests)
}

func handler(w http.ResponseWriter, r *http.Request) {

    incRequests()

    // handle the request here ...
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}