Go 语言被称为云计算时代的 C 语言,它在软件开发效率和运行效率之间做出了绝佳的权衡。这使得它既适应于互联网应用的极速开发,又能在高并发、高性能的开发场景中如鱼得水。正因如此,许多互联网公司,尤其是云计算领域的创业公司都选择 Go 语言作为其技术栈的重要组成部分。因此,对于广大的开发者而言,关注和学习 Go 语言就十分有必要了。
在高手问答第 149 期中,我们围绕 Go 进行了提问,并邀请了 @hyper0x(郝林)作为高手嘉宾。
本文整理了此次高手问答中一些精彩的问答。
Go 语言使用场景相关的问题
Go 的主要使用场景:
- 主要场景有很多,比如网络编程,包括 Web 系统、API 应用、下载应用、游戏后端,以及各种服务器编程,例如处理日志、数据打包、虚拟机处理、文件系统,等等。相关的项目在 GitHub 上十分多,也可以参考:https://github.com/GoHackers/awesome-go-China
- 除了这些,Go 还适合分布式系统、网关类系统(微服务网关)、数据库代理器、基础服务等的开发,只要有高并发高可用需求的服务端程序都可以用 Go 开发。
- 内存数据库,谷歌开发的 groupcache,couchbase 的部分组建。
- 云平台,目前国外很多云平台采用 Go 开发,CloudFoundy 的部分组建。
- 另外 IoT 方面有 Gobot 框架,移动开发方面也有官方的解决方案(虽然还有待进一步发展)。
Go 在大数据领域的应用,以及在大数据领域的应用(海量存储,批处理,流处理,数据预测等方面)有哪些比较看好的开源或商业项目吗?
- 在数据挖掘(尤其是爬虫)、数据分析、数据存储方面,Go 都非常适合。在 GitHub 上边有很多这方面的库,尤其是挖掘和存储方面。(国产的有很多,比如:pholcus(爬虫)、TiDB(存储)等等)。
- 海量存储有很多,比如 InfuxDB、CockroachDB、TiDB。其他方面在 GitHub 上也有很多开源项目,不一一列举了。不过商业的项目目前并不多见。
- 在大数据领域,Go 和 Python 也是十分优秀的组合。
Go 作为系统编程语言意在取代 C/C++,请问有哪些系统编程使用场景?
- 谁也取代不了谁,谁也不会被轻易取代,只能说在新的时代更加适合做基础性的工作,“云计算时代的C语言”的意思是在云计算时代更适合做基础性的工作,实际情况也印证了这一点。我们可以用 Go 轻易编写系统级的基础命令,也可以用 Go 编写软件替代 C/C++ 软件,比如 Caddy 可以替代 Nginx,等等。
目前很多电商平台是用 PHP 开发的,Go 适合做电商平台的开发语言吗?
- 我司就用 Go 写了 API 网关、基础服务和基础组件,以及一些需要较高性能的应用级系统,都是全局性的基础系统。优势很明显,在开发效率和运行效率上都可以满足要求,而且绰绰有余。
- 电商用 PHP 主要都是因为开发快,但是从节省运维成本和提高运行效率的角度讲,Go 也是很不错的选择。PHP 更容易做页面渲染,而 Go 更擅长做并发任务处理。在我司是这么划分的。PHP 在某些任务的开发效率上可能更高,但是程序运行效率是比不上 Go 的。
人工智能之类的有名的项目,目前没有是 Go 做的,如何用 Go 做人工智能?
- Go 语言由于 Google 的推动进入 AI 领域是必然的。目前 Go 做人工智能相关的工作主要是搭 Tensorflow 的车,因为深度学习框架 Tensorflow 已经有 Go 的 API 了。相信 Go 会逐渐成为主要角色的。
创业公司都选择 Go 语言作为其技术栈合适吗?
- 现在有很多公司都这么做,不过一个技术型公司一般不会只选用一种语言作为基础技术栈的。我推荐创业团队选用 Go 语言作为其基础技术栈(之一)。
Go 语言的优势
Go 有什么优势:
- 部署简单:Go 编译生成的是一个静态的可执行文件,除了 glibc 外没有其他外部依赖。这让部署变得异常方便
- 并发性好:语言层面支持并发,这个是 Go 最大的特色。Goroutine 和 channel 使得编写高并发的服务端软件变得十分容易,很多情况下不需要考虑锁机制以及由此带来的各种问题。
- 良好的语言设计:从工程的角度看,Go 的规范简单灵活,自带完善的工具链,例如 gofmt 可自动排版代码
- 执行性能好:适合编写瓶颈业务,非常节省内存
- 丰富的标准库:内置了大量的库,还有强大的网络库
Go 语言相比 Java、PHP 这类时下用得最广的语言在执行速度跟并发编程上优势很明显,除了这两点外,Go 还有别的优势吗?
- 工程化能力、开发和运行效率上的权衡是 Go 很突出的两个特色。这两方面初看没什么,但细究起来真正是为软件工程的实施准备的,能起到非常大的作用。当一个团队去做一大坨项目或者很大的工程的时候,优势还是很明显的。
Rust 没有 GC,Nim 有 GC 但编译成 C 性能更好,请问 Golang 在和 Rust、Nim 的竞争中会逐渐处于弱势吗?
- 看一门语言要看它的“干爹”、生态建设和发展历史。Nim的语法我也很喜欢,但是没有大公司支持,发展没有保障。
- Rust 也是一门很不错的语言,基本上是纯社区支持,但是学习门槛很高,生态也不是太万重山,需要观望。
- 对于我来说,Go 非常适合技术团队使用。当然,如果只是把玩的话 Nim 还是很不错的,如果想锻炼心智 Rust 也是一个很不错的选择。
Go 语言和 Python 相比,感觉 Python 语言在云计算、数据挖掘和机器学习更加有优势。看了好多机器学习的库都有 Python 版本的而没有 Go 版本的。一直听说 Go 语言的性能比 Python 强悍,不知道具体哪方面强于 Python。
- Go 语言已经涉足数据挖掘领域,正在开始涉足数据分析和机器学习领域。
- 性能强是肯定的,只考虑解释型语言与编译型语言的差别就可以断定性能差别,更何况 Go 语言的性能在编译型语言中也是佼佼者。可以自己用不同语言写同一个 Web Server 测试一下。
相比于 Python、Perl、Ruby 等后端开发语言,Go 有哪些优势呢?
- 与脚本语言相比,Go 的优势很明显 — 性能好。当然,缺点就是语法糖太少,不过这也是 Go 的工程化理念的一种体现。
- Go 的并发编程模型是非常独特的,它省去了开发者自己去处理复杂的并发处理场景。这一点非常值得广大开发者研习。
Go 语言支持多线程吗?
- Go 语言在内核线程之上构建了用户级线程机制和模型,可以说 Go 的并发模型就是建立在内核线程之上的。Go 完美地包装了传统的多线程编程模型,并且有效屏蔽了多线程编程的复杂度。
Go 语言生态发展相关的问题
Go 2.x 可能会有哪些变化?你认为泛型等高级语法,Go 会支持吗?
- 现在谈 Go 2.x 还太早,你可以到 GitHub 上的 Go 官方项目中搜索带 go2 标签的 issue。不过即使这样也无法完全推测 Go 2.x 的确切特性集合。
- Go 发布 2.x 的时候会支持范型,就我个人而言,最希望添加的特性也是泛型,但并不是没有泛型就不行。
谷歌会不会部署 pip、npm 这样的中心仓库来推动 Go 的发展?感觉目前 Go 的管理太过松散了。
- Go 官方正在开发第三方依赖管理工具 dep,但没听说准备开发类似 maven 的工具,不过后者其实可以很容易通过 dep(或glide)+自制中转站+GitLab 来满足大部分需要。
Java 的生态非常繁荣,Go 在生态建设方面发展如何?
- Go 的生态的优势目前还是在云计算、微服务和数据挖掘,正在向机器学习等新兴领域延伸。据我所知,一些机器学习和机器人领域的创业公司已经在使用它了。
- 作为使用人数较多的国家,Go 在我们国内的发展势头非常好。无论大公司还是创业公司,使用 Go 的比例在不断增大。
Golang 会取代 Java 的地位吗?未来 Go 的发展前景如何?
- 基础技术栈是很难被取代的。我们应该采取开放的心态,多个技术栈并行使用。
- 有着 Google 引领的技术潮流,Go 应该会有着很好的发展前景。
Go 使用过程中的相关问题:
之前了解到 Go 的 GC 机制存在缺陷,会导致服务进程阻塞,并发机制短暂失效,这个问题在 1.8 中有解决吗?
- 早在 Go 1.4,Go 官方就已经开始着手改进 GC 了,经过这么多版本的努力,至今的 GC 已经完全不是问题了,具体介绍请见:http://www.infoq.com/cn/articles/2016-review-go
Golang 运行时是包含 runtime 的,也是拥有垃圾回收的,与传统的 Java 相比性能有优势么?您在使用 Golang 语言的过程中遇到过那些问题呢?
- 关于对比,你可以参考这篇文章:https://making.pusher.com/golangs-real-time-gc-in-theory-and-practice
- Go 语言以前被人诟病的是 GC 造成的调度停顿时间太长,但是现在已经完全不是问题了。
Golang 可以通过什么方式与其他语言进行交互,取长补短呢?
- 在语言层面有官方的 cgo。
- 不过建议使用基于通用协议的方式进行交互,比如 thrift、grpc 等,异构系统就是这么来的。
Go 语言使用消息传递的方式实现并发,同时也是支持同步锁并发,请问 channel 方式和同步锁方式的优缺点;Go 语言目前通道是在单应用内,后续是否可以支持分布式通道开发呢?
- channel 更符合 Go 的风格,被传输的值会被复制,所以一般来说很安全,锁的适用场景一般是封装并发安全对象或者保护全局变量。channel 最大的优势是让并发编程非常方便和清晰,缺点是稍微比锁重一些。
- 分布式通道的其实可以用很多第三方框架或软件实现,比如 gPRC、Thrift 或者各种 MQ。
Go 开发中有什么坑或注意点?例如因为跟其他常规语言的编程或设计思路不同,而容易导致错误的使用。
- 简要说一下,在使用 slice类型、channel类型、go语句、defer语句、函数传参、变量赋值、接口运用等方面都有一些需要注意的地方。例如,一个 slice 值的底层数组在什么情况下是什么样子的,知道了这个才能更好地运用 slice。
- 又例如,怎样操纵 channel 值才能避免阻塞或 panic。
Go 的一些模块比较慢,比如 Go 的 log,json 部分都有些慢,请问生产环境只能用一些第三方来替代么?关于这里踩过哪些坑,你们又是如何填坑的呢?
- log 也是 IO,所以必然慢,这需要在性能和日志完备性方面做权衡。在很多时候,日志的内容需要仔细斟酌。慢一般有两方面原因,一个是有计算量(直接原因),一个是有额外内存分配(间接原因),需要从这两方面优化。
- 另外我们是在 logrus 和 Uber 的 zap 上简单的封装了一层,统一接口,前者扩展性好,后者性能较好。json 这块其实我们还是用的官方方案,不过有些简单 json 就直接拼接字符串了,性能会好一些。
并发和并行有些区别,请问写出真正并行的程序有什么建议呢,现在只是配置下 GOMAXPROCS。
- Go 1.5 以后就不用设置这个环境变量了,默认值与当前机器的逻辑 CPU 数量相同,可以充分利用多核计算。
- 用 Go 语言写程序只要关注怎么并发就行了,并行的事情交给 runtime。但是与很多技术一样,需要知道底层的原理才能更好的搭建上层建筑。
Go 的底层是如何实现“鸭子模式”的,原理是什么?对性能是否有影响?
- 你可以看一下这里 https://golang.org/doc/faq#guarantee_satisfies_interface,具体的方式可以阅读 Go 编译器的源码。
- 当然会有性能影响,但是写程序和做软件一定要考虑维护期(生命周期的 90%),要有良好的设计。这很重要。另外,把一个非接口类型(且非指针类型)的值赋给一个接口类型的变量会产生新的内存分配。这点需要注意。
Go 的包管理有什么好的成熟方案吗?
- Go 官方在做一个叫 dep 的官方解决方案,但是正式放出还有一段时间。在这之前,我个人首推 Glide,另外 gb 在一些情况下也是适用的。
有什么比较强大的 Go 开发工具?
- 个人觉得图形化的开发工具中,VS Code、gogland、LiteIDE 都比较好用
- Intellj IDEA + Go plugin 也是不错的选择
书中有 Go Tool Trace 的使用么,求推荐 Golang 各种 tool 的教程说明,pprof、cpu、内存、竞态条件等。
- 书中并没有 Go Tool Trace 的使用方法,我另外有一份免费的 Go 命令教程,地址是: https://github.com/gohackers/go_command_tutorial。这份教程上有大多数 Go 命令的使用介绍,但是由于精力有限,没有 Go Tool Trace 的使用方法。我也希望能有 gopher 帮我完善这份教程。当然,一旦我有时间也会去补上。
在 Windows 环境下,想输出 GC 信息,CMD 中:set GODEBUG=gctrace=1 mygoapp.exe,这样并没有信息输出。
- 请参考 https://golang.org/pkg/runtime/#hdr-Environment_Variables。另外你要确认环境变量是否设置正确。
其他相关问题
目前做 Java 开发,但是非常喜欢Go,准备转到 Go,对于国内 Go 的行情您认为怎样?有什么要注意的?
- 行情肯定是没有 Java 和 PHP 好,但是正在快速向前冲。如果你真心喜欢 Go 语言,建议找一个专职的 Go 开发工作。当然,在目前岗位上直接用 Go 去写一些东西、完成一些任务,是更稳妥的办法。把这门技术应用于实际、产生价值,才是最重要的。
- 主要需要注意设计和编写程序的方式,Java 太 OO 了,所以 Java 程序员很容易陷入 OO 思想不能自拔,其实除了 OO 还有其他优秀的编程思想。BTW,我当初就是从 Java 转过来的。
- 关于编程思想的转变方面,还可以参考一位 Go 大牛博客 http://tonybai.com/2017/04/20/go-coding-in-go-way 中的内容。
之前用了五六年的 C#,后来转成 Node.js 开发,到现在有三年了,使用 Go 开发相比 Node.js 有什么优势?有必要学习 Go 语言吗?
- 如果你厌恶 Node.js 的 callback hell,可以毅然决然的转 Go,Go 的并发编程模型会大大降低开发者的心智负担,让你轻松开发并发程序。
- 此外,Go 的程序设计哲学与 Unix 的哲学很相近,工程化的理念也非常值得吸纳。
有疑问加站长微信联系(非本文作者)