pacakge expvar 内部实现
29 Oct 2017内部数据结构
// Var is an abstract type for all exported variables.
type Var interface {
// String returns a valid JSON value for the variable.
// Types with String methods that do not return valid JSON
// (such as time.Time) must not be used as a Var.
String() string
}
// All published variables.
var (
mutex sync.RWMutex
vars = make(map[string]Var)
varKeys []string // sorted
)
vars 的 key 是 Var 绑定的名称,Var 是 一个有 String() 方法的 interface。
func NewInt(name string) *Int {
v := new(Int)
Publish(name, v)
return v
}
// Publish declares a named exported variable. This should be called from a
// package's init function when it creates its Vars. If the name is already
// registered then this will log.Panic.
func Publish(name string, v Var) {
mutex.Lock()
defer mutex.Unlock()
if _, existing := vars[name]; existing {
log.Panicln("Reuse of exported var name:", name)
}
vars[name] = v
varKeys = append(varKeys, name)
sort.Strings(varKeys)
}
NewInt 创建一个名字为 name 的 Int 对象,并将这个对象名字和对应对象的指针保存到 map vars, 并返回这个对象的指针 Int对象的指针有 Add()、Set()、String()、Value()等方法
// Int is a 64-bit integer variable that satisfies the Var interface.
type Int struct {
i int64
}
func (v *Int) Value() int64 {
return atomic.LoadInt64(&v.i)
}
func (v *Int) String() string {
return strconv.FormatInt(atomic.LoadInt64(&v.i), 10)
}
func (v *Int) Add(delta int64) {
atomic.AddInt64(&v.i, delta)
}
func (v *Int) Set(value int64) {
atomic.StoreInt64(&v.i, value)
}
expvar 会向 http.DefaultServeMux 注册了 /debug/vars
的 handler
如果你的 Server 有自己的 handler ,那么 需要手动注册一下 /debug/var
的 handler
func init() {
http.HandleFunc("/debug/vars", expvarHandler)
Publish("cmdline", Func(cmdline))
Publish("memstats", Func(memstats))
}
使用示例1: 不使用自己的hander
package main
import (
"expvar"
"net/http"
"fmt"
)
var visits = expvar.NewInt("visits")
func handleFunc (w http.ResponseWriter, r *http.Request) {
visits.Add(1)
fmt.Fprintf(w,"你是第%d 访客\n", visits.Value())
}
func main() {
http.HandleFunc("/", handleFunc)
http.ListenAndServe(":8080", nil)
}
使用实例2: 使用自己的 handler
package main
import (
"fmt"
"github.com/julienschmidt/httprouter"
"net/http"
"log"
"expvar"
)
var visited = expvar.NewInt("visited")
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
visited.Add(1)
fmt.Fprint(w, "Welcome!\n")
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
visited.Add(1)
fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}
func Vars(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
expvar.Handler().ServeHTTP(w, r)
}
func main() {
router := httprouter.New()
router.GET("/", Index)
router.GET("/hello/:name", Hello)
router.GET("/debug/vars", Vars)
log.Fatal(http.ListenAndServe(":8080", router))
}