代码 > 我为什么喜欢golang
2018-02-12
接触golang一年了,自己的小框架,准确的说是网络代码包也离预期完成了十之七八了。
的确发现,自己挺喜欢这门语言的。
而反思为什么喜欢这门语言,其实很简单,因为我菜,而且知道自己菜。
一直以来,用过的语言里,可以说最不喜欢的就是PHP和Javascript了。
我不知道为什么这两门语言会有人觉得简单。
对我而言,很难。
不能确定的变量类型,各种隐藏着的类型转换。
只要代码堆积的一多,自己都不感去想有多少问题。
反观golang。
静态编译,有defer,chan,go来降低心智负担,真的很省力。
其实早早的就知道,自己只能算是个票友,能力有限,一直想各种方法来降低写代码时的心智负担,使得尽可能的作出更复杂的程序。
毕竟,换语言容易,换脑子难。
我菜,我自知,我用golang.
代码 > 开始试用微软的visualstudio tfs
2018-01-30
之前的私有代码托管都是放在bitbucket的。
说实话,bitbucket是个不错的服务。但是和github同质化太严重了。
和github同质化严重的,之前还有code.google.com和codeplex,现在都已经在欢声笑语中打出了GG了。
所以,虽然已经用了好几年bitbucket了,但在知乎上看了大软吹轮子哥推荐,还是试用一下。
到目前为止,感觉还算良好
代码 > https的效率影响
2018-01-27
blog重构后,在本地跑了下性能测试。发现https,至少是nginx的默认设置对效率的影响还是很大的。
本地环境:rmbp 13,2014 mid 中配
debian testing,nginx version: nginx/1.13.8
测试结果:
使用证书和不使用证书,在某些情况下能有一个数量级,也就是10倍的效率差距。
测试结论:
普通应用全上https证书自然是没问题的,毕竟前端的负载均衡是最容易扩充的。真的要求极限性能的地方,比如内网验证服务,还是要考虑下的。成本敏感的话,全站https还是需要考虑下的。
测试数据:
直连:
ab -n 10000 -c 100 http://127.0.0.1:8000/site/blogi/150-
Requests per second: 19273.02 [#/sec] (mean)
nginx反代:
ab -n 10000 -c 100 http://local.jarlyyn.com:1000/site/blogi/150-
Requests per second: 12578.55 [#/sec] (mean)
nginx https(let's encrypt证书)反代:
ab -n 10000 -c 100 https://local.jarlyyn.com/site/blogi/150-
Requests per second: 1173.36 [#/sec] (mean)
nginx配置:
server {
ssl on;
ssl_certificate_key /ssl/local.jarlyyn.com.key;
ssl_certificate /ssl/local.jarlyyn.com.fullchain.crt;
server_name local.jarlyyn.com;
listen 443 http2;
access_log off;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8000;
}
}
代码 > 记录:golang中错误在for range中对值使用了指针。
2018-01-08
某段程序出错,最后定位到错误在大概这样的结构
for _, v := range data {
c <- &v
}
这样,整个cannel里,都只有最后一个v值
整理了下思路,也很好理解。
这样的代码某种角度相当于
{
var v int
for _, v = range data {
c <- &v
}
}
而非
for _, v = range data {
var v int
c <- &v
}
那自然都是最后一个值了。
作为一个每个循环中都要使用的值,自然不可能不停的创建新的。这太不环保。
但直接的写法里比较难直接看出来。
记录下,以后至少记得解决的方向
代码 > 记录:通过golang的reflect包创建value的指针
2018-01-03
这个问题困扰了我一定时间,搜了一圈后发先自己2了
先用New创建空指针
然后给指针的Elem设置为具体的值。
主要一直以为New出来的对象没发用,是个zero value,到处panic,没反映过来elem还是可以用来set的。
其实想想也是,如果没法赋值的话,这个New函数有什么用……
大概代码:
var v = mapvalue.MapIndex(reflect.ValueOf(key))
var vp = reflect.New(v.Type())
vp.Elem().Set(v)
代码 > 用nssm为windows添加服务
2017-09-29
最近牵涉到需要在为客户做一个提供api转发的守护程序,研究了下什么方法最方便,立刻看中了nssm
nssm有命令行以及图形界面,通过简单的bat程序就能非常容易的做一个注册服务的安装程序。
具体网址:
https://nssm.cc/
代码 > golang中生成prefix形式的xmlns的xml文件
2017-09-17
最近在做一个调用soap接口守护程序。
找了一圈golang的库,都不是太好用,就干脆用仿照soap代码,自己生成和解析xml代码了。
然后发现golang 至少 1.9的xml库,虽然可以解析prefix,但不能生成prefix。查了一圈只能用模拟的方式自行去实现。
也就是自己去生成xmlns的属性,自己填入。
具体来说,代码结构如下:
type GetPartsInfoListRequest struct {
SoapNS string `xml:"xmlns:soap,attr"`
TemNS string `xml:"xmlns:tem,attr"`
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ soap:Envelope"`
}
req := GetPartsInfoListRequest{}
req.SoapNS = "http://schemas.xmlsoap.org/soap/envelope"
req.TemNS = "http://tempuri.org/"
bytes, err := xml.Marshal(req)
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
另有之前遇到的错误
The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/xxxx'.
这是构建请求xml时没有加入ws-a信息
参考 https://social.msdn.microsoft.com/Forums/vstudio/en-US/ed32328d-e3ad-47dd-bcb0-3db9e6205f9c/actionmismatchaddressingexception?forum=wcf
解决方案是在soap header中加入wsa的header。大概代码为
<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Action>http://tempuri.org/xxx</wsa:Action>
</soap:Header>
代码 > 出色的golang sql操作库sqlx
2017-03-31
在用标准去的sql库裸写了博客和某个新浪爬虫后,还是使用了sqlx做新的内部项目。
总的来说,非常好用。
https://github.com/jmoiron/sqlx
总体来说,它最重要的特性包括:
1.NamedExec,用一个struct来储存所有的参数。最关键的,不需要每个参数都用到
2.get和select,可获得一个或者多个数据结构。不需要在一个一个写赋值了。
3.Named。可以对象和命名的查询字符串转为传统的查询字符串和args。为复杂的查询拼接提供了极大的帮助。
总体来说在性能影响尽可能小的情况下,大幅度的提高了开发的效率
代码 > 慎用golang中的append操作
2017-02-28
golang的slice是一个极好用的东西。
用slice自然少不得会使用append。
我自己做的midderware组块核心就是一个Func的slice
不知不觉就踩了一个坑。
具体来说,在加入csrf模块后,发现了奇怪的现象。
本来访问正常的页面,在路由加入2个middleware后报404,一个Middleware时不报。
为了解决这个问题,差不多把所有有关无关的代码都看了遍。无数的断点和测试,一步一步f11调试。
最后,锁定问题为:
在加入的middleware数量达到两个后,只有随后一个设置的路由起效。
调整代码顺序可以证实。
实在没办法后,脑洞大开。
觉得分明就是golang做了优化么,把相同的仅包含相同内容slice的struct当成了同一个。
把Use函数做了下修改
从
target.SetHandlers(funcs...)
改为
f:=make(funcxx,len(funcs))
copy(f,funcs)
target.SetHandlers(f)
问题解决
一瞬间我感觉到了地鼠对我有深深的恶意
代码 > 推荐Golang序列化库vmihailenco/msgpack
2017-02-27
之前用golang标准库的gob做2进制序列化,缓存页面。
用下来很难用,没法直接interface{}用自定义结构,使用前要先注册。
这次换了https://github.com/vmihailenco/msgpack这个库。十分好用。
和json库一样可以直接传入interface{}序列化/反序列化。
速度比gob快很多。
之前我Blog缓存过得页面,在我的rmbp13上速度大概是2x,xxxns
换为msgpack后直接提升为10,xxxns
去掉5,xxx必要的处理和middle之类
效率在我这个场景下高了3倍左右。