内容简介:Golang 公共变量包——expvar
写在前面
expvar
包是 Golang 官方提供的公共变量包,它可以辅助调试全局变量。支持一些常见的类型: float64
、 int64
、 Map
、 String
。如果我们的程序要用到上面提的四种类型(其中,Map 类型要求 Key 是字符串)。可以考虑使用这个包。
功能
- 它支持对变量的基本操作,修改、查询这些;
- 整形类型,可以用来做计数器;
- 操作都是线程安全的。这点很不错。相信大家都自己整过全局变量,除了变量还得整的锁,自己写确实挺麻烦的;
-
此外还提供了调试接口,
/debug/vars
。它能够展示所有通过这个包创建的变量; -
所有的变量都是
Var
类型,可以自己通过实现这个接口扩展其它的类型;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 }
-
Handler()
方法可以得到调试接口的http.Handler
,和自己的路由对接。
这些基础的功能就不多说了,大家可以直接看官方的 文档 。
调试接口
看源码的时候发现一个非常有意思的调试接口, /debug/vars
会把所有注册的变量打印到接口里面。这个接口很有情怀。
func init() { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline)) Publish("memstats", Func(memstats)) }
源码
var ( mutex sync.RWMutex vars = make(map[string]Var) varKeys []string // sorted )
-
varKeys
是全局变量所有的变量名,而且是有序的; -
vars
根据变量名保存了对应的数据。当然mutex
就是这个 Map 的锁; -
这三个变量组合起来其实是一个有序线程安全哈希表的实现。
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 } 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) }
- 这个包里面的所有类型都实现了这个接口;
-
以 Int 类型举例。实现非常的简单,注意
Add
和Set
方法是线程安全的。别的类型实现也一样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) } func NewInt(name string) *Int { v := new(Int) Publish(name, v) return v }
-
将变量注册到一开始介绍的
vars
和varKeys
里面; - 注册时候也是线程安全的,所有的变量名在注册的最后排了个序;
-
创建对象的时候会自动注册。
func Do(f func(KeyValue)) { mutex.RLock() defer mutex.RUnlock() for _, k := range varKeys { f(KeyValue{k, vars[k]}) } } func expvarHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") fmt.Fprintf(w, "{\n") first := true Do(func(kv KeyValue) { if !first { fmt.Fprintf(w, ",\n") } first = false fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) }) fmt.Fprintf(w, "\n}\n") } func Handler() http.Handler { return http.HandlerFunc(expvarHandler) }
-
Do
方法,利用一个闭包,按照varKeys
的顺序遍历所有全局变量; -
expvarHandler
方法是http.Handler
类型,将所有变量通过接口输出,里面通过Do
方法,把所有变量遍历了一遍。挺巧妙; -
通过
http.HandleFunc
方法把expvarHandler
这个外部不可访问的方法对外,这个方法用于对接自己的路由; -
输出数据的类型,
fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
,可以发现,值输出的字符串,所以输出的内容是String()
的结果。这里有一个技巧,虽然调用的字符串的方法,但是由于输出格式%s
外面并没有引号,所有对于 JSON 来说,输出的内容是对象类型。相当于在 JSON 编码的时候做了一次类型转换。type Func func() interface{} func (f Func) Value() interface{} { return f() } func (f Func) String() string { v, _ := json.Marshal(f()) return string(v) } func cmdline() interface{} { return os.Args }
-
这是一个非常有意思的写法,它可以把任何类型转换成
Var
类型; -
Func
定义的是函数,它的类型是func() interface{}
-
Func(cmdline)
,使用的地方需要看清楚,参数是cmdline
而不是cmdline()
,所以这个写法是类型转换。转换完之后cmdline
方法就有了String()
方法,在String()
方法里又调用了f()
,通过 JSON 编码输出。这个小技巧在前面提到的http.HandleFunc
里面也有用到,Golang 的 程序员 对这个是真爱,咱们编码的时候也要多用用啊。
不足
感觉这个包还是针对简单变量,比如整形、字符串这种比较好用。
- 前面已经说了,Map 类型只支持 Key 是字符串的变量。其它类型还得自己扩展,扩展的话锁的问题还是得自己搞。而且 JSON 编码低版本不支持 Key 是整形类型的编码,也是个问题;
-
Var
接口太简单,只有一个String()
方法,基本上只能输出变量所有内容,别的东西都没办法控制,如果你的变量有10000个键值对,那么这个接口基本上属于不能用。多说一句,这是 Golang 设计的常见问题,比如日志包,输出的类型是io.Writer
,而这个接口只支持一个方法Write([]byte)
,想扩展日志包的功能很难,这也失去了抽象出来一个接口的意义。 -
路由里面还默认追加了启动参数和
MemStats
内存相关参数。我个人觉得后面这个不应该加,调用runtime.ReadMemStats(stats)
会引起 Stop The World,总感觉不值当。
总结
看到就写了,并没有什么沉淀,写得挺乱的。这个包很简单,但是里面还是有些可以借鉴的编码和设计。新版本的 Golang 已经能解析整形为 Key 的哈希表了,这个包啥时候能跟上支持一下?
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 全局变量,静态全局变量,局部变量,静态局部变量
- python变量与变量作用域
- Python基础-类变量和实例变量
- python编程(类变量和实例变量)
- 03-Golang局部变量和全局变量
- jquery-plugin中的全局变量或局部变量
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人类思维如何与互联网共同进化
[美] 约翰·布罗克曼 / 付晓光 / 浙江人民出版社 / 2017-3 / 79.90元
➢人类是否因互联网的诞生进入了公平竞争的场域? “黑天鹅事件”频频发生,我们的预测能力是否正在退化? 智人的第四阶段有哪些特征? 全球脑会使人类成为“超级英雄”吗? 虚拟现实技术会不会灭绝人类的真实体验? 还有更多不可预知答案的问题,你将在本书中找到属于自己的答案! ➢ 我们的心智正和互联网发生着永无止境的共振,人类思维会因此产生怎样的进化效应?本书编者约翰•布......一起来看看 《人类思维如何与互联网共同进化》 这本书的介绍吧!