我是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不同。
那我怎么能实现这个目标呢?
答案 0 :(得分:3)
在函数之外,您不能使用短变量声明:=
。在定义全局变量的函数之外,您必须使用variable declaration(使用var
关键字):
var count int
它会自动初始化为int
的零值0
。
<强>链接:强>
我建议您阅读Go Language Specification的相关部分:
注意:强>
由于每个请求的处理都在其自己的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))
}