go语言编程之旅,Go语言编程之旅:一起用Go做项目
背景我们团队的后端技术栈是Python,具体的软工做法在django/python中有详细描述。因为我公司业务一般都是写Python,而且我自己的项目都是Python工具,所以一直想尝试体验一下围棋。
上周有空,就体验了一下Go的基础设置,用Go写了一个小服务(微信消息推送)。
这篇文章讲的是一个大画家的创新之路。如有理解上的错误和操作不当,请提出您的意见。
学习一门语言,总是习惯性地在y分钟内打开learn x,先浏览语法。
Go的特别之处在于它的关键字很少,这使得Go的语法很容易写下来。总的来说,我觉得这些语法很有意思。
loop//可以为{fmt.println (while true . 编写死循环)}/range直接。关键字data:=map[string]string { key : Value ,} for key,Value:=rangedata { fmt . println( while true . )}枚举//iota实际上已经做成了关键字//这里可以省略后两个IOTA const { unknown=IOTA//0 male=IOTA//1 Female=IOTA//2 }//也可以满足每10个定义一次枚举的偏好。//` iota2 `还可以通过按位运算const { unknown=iota * 10//0 male=iota * 10//10 female=iota * 10//20 }多表达式判断//if语句将取最终表达式值,所以这种判断很常见if f,err :=file。打开(路径);呃!=nil {返回响应(400,err。error())}//也是常见的操作如果数据,ok :=json。解组(正文);ok { return Response(400,无效JSON体)} GO例程的自然并发//GO也是非常优雅的地方。func sendTemplate() {//这里是一个需要很长时间的网络请求} FUNC句柄请求(CTX上下文){Validate ()//SendTemplate() //如果为了速度不能同步发送模板,那么我们可以用关键字‘go’来异步 go sendTemplate()}项目第一章的语法过了之后,很快就到了第二章:《如何用 go 起一个项目》。
要写代码,首先要把文档翻出来看一看。所以第一站是golang.org,官网
Go的官网其实很友好,从最基础的教你如何搭配环境,写初始项目,到有效Go之类的综合长文。
安装语言环境后,我先玩了一下环境变量GOPATH。不过后来发现go mod是Go 1.12自带的。简单了解一下概念就可以了。先戴上,直接感受一下Go的工具链。
链Python安装后,主要附带一个REPL和pip包管理器。Go安装后会附带包括fmt/test/vet/mod在内的一系列工具。
我刚开始做Go的时候印象最深的第一个工具Go fmt是一个不支持配置的代码格式化工具。它是非常严格的。prefer tab over spacego test自带覆盖,使用起来很方便。兽医似乎有自己的短绒。我玩围棋测试的时候发现是测试包的,包的概念在围棋中也很突出。例如,在调用包方法时,应该添加包名,因此在最佳实践中也有“命名不重叠”的规则。(举个栗子,比如方法应该叫xml。解析器而不是xml。XMLParser)
写业务因为我们用RESTful风格写一个提供内网接口的小服务,然后调用微信发送消息通知用户,根据Python的惯性,我们想找一个django的微信支付组合,在一周内完成业务。简单研究后,我选择了两个大工具,gin gorm。
Go的第三方库给我的感觉非常直白。因为引入第三方库的方式是直接拉GitHub master branch最新代码的Go Get-U github.com/gin-gonic/gin,感觉整个第三方社区都是基于分布式共识的。只有大家都遵守社群规范,才会没有矿码……(虽然集权会有矿码)
对于文档,其实研究阶段的读者都是GitHub README。GitHub是一个经常访问的网站,每个库的README风格都是markdown风格,很容易阅读。真正能看到godoc的地方不多。因为你是拉源代码,基本上是直接看源代码,体验和Python很像。
具体的业务代码就跳过了,没什么特别的。
当我们开始准备部署时,有许多有趣的话题。比如围棋的多环境配置。
Python (DjanGo)多环境我一直使用环境变量多配置文件。如果我去的话,我会去社区看看。基本上原理都差不多。您可以使用环境变量、多个配置文件(如yaml)和命令参数(标志库)。其实Go社区非常推荐flag,因为它可以把配置和代码(可执行文件)融为一体,更有利于维护。但是,我最终选择了环境变量多概要文件…
我们使用GitLab CI/Docker来编译和部署项目。也是CI的五个常规阶段——构建/测试/编译/Docker——构建/部署。Go的特别之处在于会引用很多GitHub和Google提供的官方代码,在国内比较慢。因此,为了加快施工速度,我们还设置了相应的加速通道来提高速度。目前从代码进入主干分支到自动释放不超过3分钟。
自己写的小服务上去了,所以首先wrk要测试QPS。
Python(Django)的默认其实是同步模式,基础支持的QPS很低。我们专门用gevent uwsgi协同模式对其进行了调整,这是一个简单的界面,可以获取服务器的当前时间。在1CPU 4G内存的小破机上,Python(gevent)的QPS可以达到1000,而Go (Gin)未经调优的QPS可以达到10000。好样的,去吧。
在社区玩Go的那一周,其实我真正有效的编码时间并不是很长,大部分时间都在各种Go的社区最佳实践文档中徘徊。
在我眼里,除了Go语言本身的很多亮点,Go的整个语言社区操作也是值得其他语言学习的。比如上面说的官方工具链,可以有效的提高所有项目的下限。Python去年也刚刚发布了一个格式化工具black,号称是
the uncompromising code formatter
。(Python:不急,我现在正在学)说了这么多看似中性实则是情怀的发言,我来集中总结一下我的感受。
写围棋的时候,我能直接感觉到我很有味道。这是一个水瓶,我在很多地方都能感知到语法简化的可能性,但我的语言表达能力并没有得到优化。比如Go 2草案中的check关键字,我隐约觉得基于panic recover也可以实现类似的机制,但是真的想写也写不出来。而Python,感觉可以写成Lisp。
另一个是库的使用,或者说“语言生态”。无论是平时用的标准库,还是后端业务用的各种三方库,还是工程中单元测试和质量控制用的库,我用的时候都只能做现场调研。
总之,因为基础知识的欠缺,熟练度的不足,写围棋的过程总有一种“我喜欢美食,却不知道这个”的奇妙感觉。
我对Go食物的喜欢并没有阻止我表达我的爱:)
Go揭示了一个很老套的KISS原理,它甚至给我的感觉是比Python更简单。例如,最佳实践会告诉您,“不要过早打开文件。一个目录十个文件就能解决的问题,不需要分层。”
与Python相比,Go的执行速度透露出一种不合理的速度。Python对并发模型的深入理解,在调优CPU和语言参数后,还是比Go落后一个数量级……(但Python在开发速度上还是极快的……)
另外Go有个可爱的地鼠~
目前我们后端的主要技术栈是Java和Python,我主要写Python。
就我短暂的体验来看,Go在关键的高性能服务上会有不错的表现,但是在Web层的新服务和多服务的原型上,Python神奇的开发速度还是无人能及的(akimbo)
目前流行的后端框架基本都是语言无关的,我们可以根据不同服务的适用场景选择合适的技术栈。
企业在选择技术栈时,其实会考虑其他更现实的因素,比如开发人员的招聘难度、代码库和技术栈的统一、大团队的解耦管理等。其实这些都很有深度,值得探讨。
写了一个星期的Go,我更加坚信自己的理念:“工程师是解决问题的人,技术是解决问题的工具。软件工程做不好,工具就很难用。捅人和杀人有什么区别?”
下周的体验卡有点太短了,很想。
如果有时间跟进,我会继续研究这些关于围棋的话题:
生产环境中的服务部署状态。Go的服务可视化(监控、日志、跟踪)使用黑魔法,使基础数据库具有更高的语言表达力跨语言服务交互实践。