说说 Golang 的使用心得

本贴最后更新于 3284 天前,其中的信息可能已经时移世改

13年上半年接触了Golang,对Golang十分喜爱。现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的。一直有想法写点Golang相关的总结或者感想,决定还是在年前总结下吧。注明下:我只是Golang的喜好者,不是脑残粉,也无意去挑起什么语言之争。

特性少,语法简单。GO是崇尚极简主义的,提倡少即是多。这点在它的Spec上尤其凸显,一下午的时间绝对可以看完。GO的特性很少,很多GO的使用者都反馈,GO的关键字至少完全可以记在大脑里。同时它的语法极为简单,而且语义清晰。

部署方便。GO是一个强类型静态语言,可以把代码编译为本地机器指令。它的RUNTIME是会在编译时一起链接到执行文件中,这也就意味着我们不需要像JAVA那样装一个JVM。而且编译出的执行文件本身不依赖于其他动态库,完全可以做到轻松的发布。当然,如果你用GO编写了调用一些动态库接口的代码,那么还是需要根据实际情况来部署这个动态库的。这点在很多从python/java转到go的朋友来说,非常喜欢。

有较完善的标准库并且较为健壮。GO自身带的标准库是比较全面的,从文件归档、压缩、加密、数据库到数据序列化,字符格式化、校验和以及网络库、同步库等应有尽有。基本上能够满足很多基本的需求了。更好的是,这些标准库的质量都非常高,都很健壮。接口也较为简单,有清晰的文档说明。同时随着这两年的发展,GO的第三方库也多了起来,虽然可能没有像python那么多,但是较其发展时间来说,还是非常不错的。

集成测框架。在之前用C++写代码时,写单元测试不是个容易的工作。需要一些技巧和努力才可以做起来。但是在GO中集成了单元测试框架,只要源码文件以_test.go结尾,就可以直接通过go test执行单元测试。同时还提供了代码测试覆盖率工具,可以很容易实施自动化测试。除此之外,还集成了基准测试框架功能,可以很容易的测量自己写的函数的运行效率。另外,还有性能剖析器,可以在运行时,测试时剖析程序的瓶颈点,进而可以进行优化。

健全的代码风格与检查工具。当初学GO的时候,很多文章和书都会提到go fmt这个命令,统一了代码风格。我觉着这点实在是解决了风格之争了。带来的影响就是别人写的代码感觉也是自己写的一样。还有golint,可以按照go team的风格和要求来写代码。还有go vet可以用来检查一些在GO中很隐蔽的坑。

简单却强大的包管理。GO的包管理可能在很多其他语言的包管理看来太弱了,但是在我看来,它解决了我需要的两个问题,一个是循环依赖问题,GO是拒绝有循环依赖关系的包;二是包的初始化,每个包的文件都可以实现一个init函数,用来在导入时执行。这点在分工合作时非常有用。

容易编写跨平台代码。如果你用纯GO,不牵扯到CGO的话,你可以非常容易的做到跨平台。只需要在文件后缀.go前,引入_linux,_windows,_x86,_x64等字符为文件名前缀的结尾就可以做到只在对应的平台中编译。GO还有build constraints控制代码在什么条件下编译。如果你用到了CGO,就牵扯到了C的跨平台问题,所以稍微麻烦那么一些,但是问题也不是太大。

垃圾回收。GC的存在极大的降低了并发代码的编写,而且还提供了程序的健壮性。做为一个从C/C++做起,有过驱动开发经验的程序员来说,GC这个东西是我一直没有涉猎过的。对我来说GC就等于噩梦。但是当我开始试着接受GC时发现,GC真的是解决了程序员的生产力,极大的提高了效率。虽然目前来说GO已经1.4版本了,但是GC还算不得上优秀,按照GO的路线图,后面会有更优秀的GC实现添加进来。

接口与struct。在第一次学习GO的interface的时候,我第一反应是这就是我想要的。虽然很多人也在说GO的这个interface的不好,而且说的很有道理,比如老赵的《为什么我不喜欢GO语言式的接口》。interface可以通过组合扩展为新的interface,struct也可以通过组合扩展为新的struct。没有继承,只有组合。可以通过匿名组合达到类似继承的效果。可以对interface进行查询,有点类似COM的味道,但是语法层面上更为简单。struct到interface的映射是隐式的,不需要声明某个struct实现了某个interface。虽然可能会出现名字上的冲突,但是可以通过wrapper进行解决。这种interface的另外一个好处是单元测试时很容易实现MOCK,这点非常喜欢。也可以看这篇文章《Go interfaces make test stubbing easy》

统一的工作布局。GO定义了项目的目录结构,比如bin目录,pkg目录以及src目录。这个和我日常的项目布局是一致的。之前用C++开发时我们也是如此安排布局,所以就这点来说,我觉着容易过渡。

内建的并发原语。提到GO就不得不提到goroutine和channel。廉价的goroutine可以让我们欢快的处理异步任务,channel可以用来交换数据。借助goroutine,可以很容易的实现高性能的服务端。goroutine及其调度器可以很容易和EPOLL,IOCP等系统机制结合起来,再通过Half Sync/Half Async模式,很容易在语法层面上达到同步形式,却不失性能。

2013年初的时候还在做一个客户端,当时使用了C++0x,其中印象最深的事情是lambad,std::function/bind,结合着线程+队列的方式,可以很容易的实现类似于Chromuim的线程模型。在处理UI与慢任务比如读文件,请求网络数据等交互时,为了保证UI的体验,使这些任务异步化是非常有必要的。如果有对Golang了解或熟悉的朋友就会明白,这是类似与Golang的goroutine+channel。但是在使用这个模型时,觉着还是繁琐了些,我要注意对象的生命周期,这个在C++虽然有各种智能指针的帮助,但是难免还会挂一漏万。而且遇到稍微的复杂的问题,比如一个慢任务接着一个慢任务时,就会涉及到一个任务链,在没有future/promise(Facebook开源的folly库中有个不错的实现futures,后来还发现WINDOWS有个基于actor model的并发库Asynchronous Agents Library非常不错,只可惜目前只在WINDOWS上使用。)机制的帮助下很容易进入Callback Hell。这样就会导致代码相对来说比较难维护,而且容易滋生BUG。好在当时这个部分的代码不是太多,而且也不是太过于复杂,很容易通过自测稳定下来。

上面虽然提到future/promise, AAL可以解决部分Callback Hell的问题,但是像future还是要用到callback。所以我在想,如果可以做到代码层面上是同步式的,背后却是异步的就爽了。GO就满足了我这个需求。

GO标准库中还提供了sync包,其中有基本的mutex说,还有RMutex这样的读写锁,还有Once,WaiterGroup等东西。基本满足日常中对锁的需求了。

GO为了帮助程序员解决在并发时经常遇到的race condition问题,还提供了相应的race condition工具。还有相应的死锁检测工具。

虽然GO社区有个slogan:”do not communicate by sharing memory; instead, share memory by communicating.“,但是每个goroutine之间并不是完全独立的,一样可以做到通过内存共享数据。这个时候只能依靠程序员自己去遵守了。而且因为goroutine不是完全独立,panic这种东西就可能会导致整个程序挂掉。这点和Erlang比起来确实不是很好。

蛋疼的defer。用习惯了C++的RAII后,十分反感GO的defer机制,但是有的时候又不得不用。原因就是这个defer不是block级别的,而是函数级别的,需要在函数返回前才得到执行。所以这就会导致在处理一些类似于文件打开,操作再关闭的逻辑时非常蛋疼,回到了C的年代,必须手动去Close。

蛋疼的panic。虽然我在C++下不怎么用异常,但是对于panic这个设计我表示非常的不满意啊。因为它会影响全局。而要捕捉panic就需要用defer。如果panic只是让当前goroutine挂掉我觉着就嗨皮坏了。

没有泛型。GO没有泛型带来的蛋疼地方是,要么就用interface{}来做运行时泛型,要么就自己手动写代码生成器。比如我自己为了生成网络协议序列化代码就撸了一个生成器。而且因为没有泛型,想实现类似C++ STL的容器与算法基本没太可能,当然方法还是有的,继续使用代码生成器。而且GO1.4干脆引入了一个叫go generate的命令。

总结

GO里面其他一些内建的数据结构,比如slice,map等,但这些也是诟病,因为它又没给予程序员可以享用range关键字的福利。

在GO的所有特性里,最喜欢就是GC,goroutine,channel以及interface。而其余的特性(比如上面我列举的很多特性)我觉着都不是太重要,其中很多都可以在工程中实践,和语言本身没有太大关系。

总结下来,这东西就是一个工程工具,各种好用,但是从设计角度讲各种粗糙,没必要过度高估。它算的上工程实践中的好朋友。在写服务端时,它是把利器,至少在写服务端程序时,我自己感觉如此。

有朋友说一个语言好不好就看它有没有开拓你的眼界,给予你新的思想,我想至少GO在这点上满足了。

  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    497 引用 • 1387 回帖 • 283 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 585 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 618 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 629 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    22346 引用 • 89408 回帖 • 1 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 595 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    15 引用 • 122 回帖
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 4 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 587 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    70 引用 • 375 回帖 • 1 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 155 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • 招聘

    哪里都缺人,哪里都不缺人。

    190 引用 • 1057 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 16 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 431 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    125 引用 • 169 回帖 • 1 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 530 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 721 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖 • 1 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 1 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    341 引用 • 708 回帖
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 130 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    238 引用 • 224 回帖
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖