概述
golang标准库expvar包提供一个全局变量的一个包,是线程安全的,主要功能可以存储一些简单的数据比如api请求次数计数,记录当前堆栈的一些信息、 gc次数、 调用cgo次数等等..... 网上相关的教程都很详细不在赘述。
问题描述
在开发wechat小程序的时候想把accessToken存在expvar中, 因为这是一个全局的变量存在这里面正适合,线程安全的,方法已经写好无需重复造轮子。但是向微信服务器发送请求验证的时候总是说我的accessToken不正确40001,起初并没有怀疑accessToken有问题 因为我从expvar中Get()出同样的值,在通过微信给的校验接口工具校验 ,也成功通过了,当时特别诧异!?怀疑过编码问题 因为用的grpc ,但很快就pass掉了, 过后想起来自己还特别可笑-_- 折腾了一上午 server端 client端到处打印调试我终于发现了问题,expvar.Get().String() 获取到的值就是有问题的。
正题
expvar.Get("foo-prefix").String() //获取到的值是`"foo"` 不是`foo`!!!
从运行结果中已经很明显了 foo的字符串加上了 双引号" " 哎脑袋疼 事后向go提了一个issuse 结果不到俩小时给我打了回来 嗯有点尴尬 说让我用exp.Value()方法 ~嗯完了 可能作者有意设置成这样的吧。
https://play.golang.org/p/kx87CKi_oEa
https://github.com/golang/go/issues/35026
结论
一、
当且仅当获取string类型的对象的时候不要用get以免造成歧义 如果非要使用 用strings包中的字符串处理或者切片处理把双引号去除掉 ,最好还是使用expvar.NewXxx() 的原对象的Value()方式来取值就不会有问题了。
二、
另一个需要注意对象的key值不能重复不然会发生键重复panic错误。
三、
还有一个最重要的一个点在使用expvar包会注册 http://127.0.0.1:port/debug/vars 路由地址,和pprof类型的形式一样,通过浏览器会看到 cmdline ,memstats信息 和你使用的NewXxx()方法注册的变量的内容 json格式,为了安全一定要考虑这个地址进行拦截等处理防止嗅探服务器信息等。
一个用go的无名小卒,有什么问题随时指出,我们共同进步!!!
完~
有疑问加站长微信联系(非本文作者)