# 关于《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语法和语义设计细节的。 一些困惑涉及到某些类型的值，主要是切片，接口和通道类型。 另外一些涉及到标准包API的使用细节。

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

我觉得最主要的原因是我当时抱着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的卖点是什么呢？

我个人的观点是，做为一门静态语言，Go却和很多动态脚本语言一样得灵活是Go的主要卖点。

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

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

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

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

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

### 《Go语言101》做了什么来消除Go编程中可能出现的困惑？

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

1. 着重于基本概念和术语的解释。如果不理解或者不熟悉这些基本概念和术语，就很难完全理解Go中的很多规则和高层次的概念。
2. 使用了值部（value part）这个术语并单独用一篇文章来解释值部。 这篇文章揭示了某些类型的底层结构，从而使得Go程序员可以更深入地理解这些类型的值。 我认为知道一些可能的底层实现对于清除某些Go编程中的困惑非常有帮助。
3. 详细地解释了内存块（memory block）。 了解Go值和内存块之间的关系对于理解垃圾收集器是如何工作的以及如何避免内存泄漏非常有帮助。
4. 将接口值视为用于包裹非接口值的盒子。 我发现将接口值视为用于包裹非接口值的盒子对于清除很多和接口相关的困惑非常有帮助。
5. 澄清了Go白皮书中的一些含糊描述，包括内嵌规则、提升方法估值和恐慌/恢复机制。
6. 汇总了许多知识点和细节，从而可以帮助Go程序员节省很多学习时间。

### 有什么其它值得一提吗？

本书不涵盖自定义泛型相关内容。 请阅读《Go自定义泛型101》一书来了解使用自定义泛型。

另外，在阐述值类型转换、值赋值和值比较规则时，自定义泛型中频繁使用的类型参数类型被特意忽略掉了。 也就是说，本书不考虑自定义泛型中的情形。