关于《Go语言101》

    大概在2016年七月份左右,不是很密集地使用了Go两年后,我觉得Go是一门简单的语言,我感觉我已经精通了Go编程。 在那个时候,我在日常编程中已经搜集了不少关于Go编程的细节。 我觉得我可以将这些细节写成一本书。 我觉得这应该是一件容易的事。

    但是我发现我错了。我太过于自信了。 在试图解释一些细节时,我发现我无法把它们解释清楚。 我对Go编程中的很多细节的底层原因产生了困惑。 随着越来越多的困惑的积攒,我觉得我对Go的领悟非常有限。 我感觉我仍然是一个Go新手程序员。

    我放弃了写那本书。

    放弃?《Go语言101》现在不是几乎已经完成了吗?

    那本曾经计划要写的书不是《Go语言101》。 放弃那本书的写作计划后,我通过阅读很多官方Go文档和网络中的各种Go文章、关注Go官方项目的问题跟踪列表和一些Go论坛、查看一些代码等途径, 逐渐地,我几乎消除了我所有关于Go编程细节中的困惑。

    我大概花了大约一年时间来消除这些困惑。 在这个时期,每当我消除了某个主题的困惑,我就以该主题写一篇博客文章。 最后,我写了大约20篇Go文章。 与此同时,我收集到了比以前更多的Go编程中的细节。 此时到了重启编写一本新的Go编程书籍的时候了。

    我写了另外大约十篇Go基础教程和另外大约二十篇Go语言中关于各种其它主题的文章。 所以现在《Go语言101》大约有50篇文章。

    你认为造成你曾经的困惑的主要原因是什么?

    我觉得最主要的原因是我当时抱着Go是一门非常简单的语言的态度去学习和使用Go。 持有这种态度阻止了我更深刻地理解Go。

    Go是一门特性丰富的语言。它的语法集虽然不大,但我们也不能说它很小。 Go中的一些语法和语义设计很简单明了,但也有一些设计略微反直觉,甚至自相矛盾。 Go语法和语义设计中有很多折衷和权衡。一个Go程序员需要相当的Go编程经验和感悟才能理解这些权衡。

    Go提供了几种基本但非必需的类型,比如切片,接口和通道。 Go编译器和运行时在实现这些类型的时候,进行了必要的封装。 一方面,这些封装为Go编程带来了许多便利,使我们不用从头实现这些类型。 但另一方面,这些封装隐藏了这些类型的内部结构, 从而对我们更深入地理解这些类型的值的行为带来了一些障碍。

    许多官方和非官方的Go教程都非常简单。 这些教程只涵盖了一般典型用例,而忽略了许多细节。 这对鼓励新手Go程序员学习和使用Go非常有好处, 但另一方面,这也使许多Go程序员对他们的Go知识掌握程度过度自信。 从长远看,这不利于一个Go程序员更好地理解和使用Go。

    标准库包中声明的某些函数和类型没有得到详细的解释。很多时候这是可以理解的。 因为很多细节解释起来很拗口和微妙,有时很难找到适当的措词来清楚地解释它们。 少量但准确的描述比大量但不准确的描述要好。但这确实也给Go程序员们留下了一些困惑。

    我认为,至少简单不是Go的主要卖点。毕竟有一些其它语言确实比Go简单。 另一方面,虽然Go是一门特性丰富的语言,但是它却也不是一门复杂的语言。 一个持有积极的学习态度的Go新手程序员可以在一年内精通Go编程。

    那你觉得Go的卖点是什么呢?

    节省内存、程序启动快和代码执行速度快合在一块儿是Go的另一个主要卖点。 虽然这三项是C家族语言的共同特征,但是在Web开发领域,很少有语言同时拥有这三个特征。 事实上,这就是我当初从Java转到Go进行Web开发的原因。

    内置并发编程支持也算是Go的卖点,虽然我个人认为它不是Go的主要卖点。

    良好的代码可读性是Go的另一个重要卖点。 我感觉可读性是Go在设计的时候考虑的最重要的一个因素。

    良好的跨平台支持也应该算是Go的一个卖点,尽管如今这个卖点并不是很新鲜。

    一个稳定的Go核心设计和开发团队以及一个活跃的社区也可以被视为Go的一个卖点。

    《Go语言101》做了以下这些方面来试图清除很多Go编程中可能遇到的困惑。

    1. 使用了值部(value part)这个术语并单独用一篇文章来解释值部。 这篇文章揭示了某些类型的底层结构,从而使得Go程序员可以更深入地理解这些类型的值。 我认为知道一些可能的底层实现对于清除某些Go编程中的困惑非常有帮助。
    2. 详细地解释了内存块(memory block)。 了解Go值和内存块之间的关系对于理解垃圾收集器是如何工作的以及如何避免内存泄漏非常有帮助。
    3. 将接口值视为用于包裹非接口值的盒子。 我发现将接口值视为用于包裹非接口值的盒子对于清除很多和接口相关的困惑非常有帮助。