最初接触 Golang 是因为工作需要。起初很不情愿地接手了一个 golang 项目,但是阴差阳错地喜欢上了这门语言。

总体来说对 Golang 的印象非常好。设计者们从一开始就对语言特性非常克制,将 golang 的语法做到简单到了极致,而且清晰明了。这样的好处是对初学者非常友好,没有太多规则需要记忆,上手非常快。这些年的发展 golang 的库发展很快,已经能够胜任很多工作。

Golang 的设计简单吸引了很多初学者,甚至收到了很多编程老兵的喜爱。著名的开源运动人士 Eric Raymond (ESR)曾对 Golang 和 Rust 的学习曲线做过了比较,挤兑了一下极难上手的 Rust,评价 Golang:

The contrast with Go is extreme. By four days in of exploring Go I had mastered most of the language, had a working program and tests, and was adding features to taste.

最近 Golang 的受欢迎程度如此之高,和它的简单易用是分不开的。如 Python 最近能够在机器学习上受如此欢迎,和它表达性强,更简单容易上手有关。很多编程高手和有多年编程经验的人很可能会对忽视易用性和易上手对一门语言,框架或是库的重要。初学者对新编程环境的适应性和学习效率很容易影响这个编程环境的增长速度。哪怕你功能强大,过高的学习曲线也会让人望而却步。

Golang 在这方面做得很好,而且 Goroutine 和 Channel,将很多较为复杂的并发表达做到非常简单明了。线程之间的数据分享一直是一个难点,也是非常容易出错的地方,但是 Golang 的 Channel 大大简化了线程间的通信的表达。

也正是因为这一点 Golang 在让分布式系统中协程的处理更加简单,也让它作为一门系统语言广受欢迎。

另外,很多在其他语言中表达较为复杂的行为也能够通过 Golang 表达得非常简洁明了。比如操作系统的 signal 处理,很多语言是通过 handler 函数处理,而 Golang 统一通过 Channel 来进行处理。

以下是一个简单但完整的例子,对信号的处理一共用了 3 行代码,加上一行 print。来自 Golang 官方文档

package main

import (
	"fmt"
	"os"
	"os/signal"
)

func main() {
// Set up channel on which to send signal notifications.
// We must use a buffered channel or risk missing the signal
// if we're not ready to receive when the signal is sent.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

// Block until a signal is received.
	s := <-c
	fmt.Println("Got signal:", s)
}

据我的了解 Golang 也存在不少问题,有很多是我认为挺容易解决的:比如模块化的问题(据说在最新的 Go 1.11 中已经开始支持 Go 模块),error 处理过于重复和冗余的问题,比较具有争议的范型(Generic Programming)问题。不支持范型使得 Golang 没有像 C++STL 那样强大的库和方便使用的数据结构,只有通过其他的方式弥补。

看到网上的讨论,Golang 还有一个问题是它 C FFI 性能的问题。由于垃圾回收和线程调度设计的问题,Golang 在调用原生 C 代码的时候性能开销很大。这也可能是限制 Golang 发展的瓶颈之一。者导致很多 C/C++ 的库,都会被 Golang 重写一遍以防止 FFI 问题。这个问题或许能够在将来得到一定的改善。

总之 Golang 给我感觉还是一门非常具有潜力继续上升的语言。

和所有语言一样,对语言特性必须了解到更深的阶段才能够真正发掘其性能。在我对 Golang 使用有了更多的经验会再谈谈感受。


Originally published at zhuanlan.zhihu.com.