<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>第 1 章 设计哲学与历史 on Go 语言原本</title>
    <link>/zh-cn/part1overview/ch01intro/</link>
    <description>Recent content in 第 1 章 设计哲学与历史 on Go 语言原本</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <atom:link href="/zh-cn/part1overview/ch01intro/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>1.1 编程语言的发展</title>
      <link>/zh-cn/part1overview/ch01intro/history/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/zh-cn/part1overview/ch01intro/history/</guid>
      <description>&lt;h1 id=&#34;11-编程语言的发展&#34;&gt;1.1 编程语言的发展&lt;/h1&gt;&#xA;&lt;p&gt;要理解 Go 为何长成今天这样，为何如此克制、如此偏执于编译速度、如此看重并发，得先看它诞生时&#xA;面对的是怎样一片语言版图，以及它想替谁解决怎样的痛。Go 不是凭空设计的，它是一群写了一辈子&#xA;系统软件的人，对当时主流语言长期不满的一次回应。读懂这段背景，全书后面对调度器、内存模型、&#xA;泛型的种种取舍，才有了一个统一的出发点。&lt;/p&gt;&#xA;&lt;h2 id=&#34;111-语言演化的几条主线&#34;&gt;1.1.1 语言演化的几条主线&lt;/h2&gt;&#xA;&lt;p&gt;编程语言半个多世纪的演化，不是一条直线，而是几股力量的反复拉锯。把它压缩成一条时间线：&#xA;1950 年代末，Fortran 让科学计算摆脱汇编、Lisp 带来高阶函数与自动内存管理；1960 年代 Algol 确立&#xA;了结构化的块与语法；1970 年代 C 与 Unix 一同诞生，给了系统程序员一种「贴着机器又不必写汇编」的&#xA;语言；1980、90 年代 C++ 与 Java 把面向对象推向主流，前者要零成本、后者要可移植与托管；同期&#xA;Python、Perl 等脚本语言以开发效率见长；2000 年代后，Go 与 Rust 代表了「重新审视系统编程」的&#xA;两种回答，一个赌简单与并发，一个赌编译期的内存安全。&lt;/p&gt;&#xA;&lt;p&gt;每一步背后，是在几个维度上做了一组&lt;strong&gt;特定取舍&lt;/strong&gt;。没有哪门语言能在所有维度上同时最优，看清这几个&#xA;维度，才看得懂各家为何长成那样：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;抽象层级&lt;/strong&gt;：从汇编的「直接操纵机器」，到 C 的过程抽象，到 C++/Java 的对象抽象，到函数式&#xA;语言的高阶抽象。层级越高，表达越凝练，离机器越远，对性能与可预测性的掌控也越弱。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存安全&lt;/strong&gt;：从 C 的手工 &lt;code&gt;malloc&lt;/code&gt;/&lt;code&gt;free&lt;/code&gt;（强大但极易出错，悬垂指针、越界、泄漏），到带垃圾&#xA;回收的托管语言（消除一大类内存错误，代价是运行时开销与停顿），再到 Rust 的所有权（编译期&#xA;保证安全，代价是更陡的学习曲线）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发模型&lt;/strong&gt;：从手工线程加锁（危险且难推理），到 CSP / Actor 等更高层的消息传递&#xA;（&lt;a href=&#34;.././csp&#34;&gt;1.3&lt;/a&gt;），到 &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; 的无栈协程。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;类型系统&lt;/strong&gt;：在「静态强类型的安全」与「动态类型的灵活」之间反复摆动；又在「名义类型」与&#xA;「结构化类型」（&lt;a href=&#34;../../../part2lang/ch04type/interface&#34;&gt;4.2&lt;/a&gt;）之间各有选择。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;工程性&lt;/strong&gt;：编译速度、构建模型、工具链、依赖管理。这一维度长期被语言设计者轻视，却恰是&#xA;大规模软件协作的命脉，也是 Go 着力最猛的地方。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;把几门有代表性的语言摆在这张坐标上，差异一目了然：&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;语言&lt;/th&gt;&#xA;          &lt;th&gt;内存管理&lt;/th&gt;&#xA;          &lt;th&gt;并发&lt;/th&gt;&#xA;          &lt;th&gt;类型&lt;/th&gt;&#xA;          &lt;th&gt;编译/执行&lt;/th&gt;&#xA;          &lt;th&gt;设计取向&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;C&lt;/td&gt;&#xA;          &lt;td&gt;手工&lt;/td&gt;&#xA;          &lt;td&gt;线程 + 锁&lt;/td&gt;&#xA;          &lt;td&gt;静态、弱&lt;/td&gt;&#xA;          &lt;td&gt;编译为本地码&lt;/td&gt;&#xA;          &lt;td&gt;贴近机器，零成本抽象&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;C++&lt;/td&gt;&#xA;          &lt;td&gt;手工 / RAII&lt;/td&gt;&#xA;          &lt;td&gt;线程 + 锁&lt;/td&gt;&#xA;          &lt;td&gt;静态、强、复杂&lt;/td&gt;&#xA;          &lt;td&gt;编译慢、执行快&lt;/td&gt;&#xA;          &lt;td&gt;表达力极大化&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Java&lt;/td&gt;&#xA;          &lt;td&gt;GC&lt;/td&gt;&#xA;          &lt;td&gt;线程 + 锁 / 虚拟线程&lt;/td&gt;&#xA;          &lt;td&gt;静态、名义、反射丰富&lt;/td&gt;&#xA;          &lt;td&gt;JIT、运行时重&lt;/td&gt;&#xA;          &lt;td&gt;「一次编写，到处运行」&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Python&lt;/td&gt;&#xA;          &lt;td&gt;GC（引用计数）&lt;/td&gt;&#xA;          &lt;td&gt;GIL + 线程 / async&lt;/td&gt;&#xA;          &lt;td&gt;动态&lt;/td&gt;&#xA;          &lt;td&gt;解释执行&lt;/td&gt;&#xA;          &lt;td&gt;开发效率优先&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Rust&lt;/td&gt;&#xA;          &lt;td&gt;所有权&lt;/td&gt;&#xA;          &lt;td&gt;线程 + async&lt;/td&gt;&#xA;          &lt;td&gt;静态、强、所有权&lt;/td&gt;&#xA;          &lt;td&gt;编译慢、执行快&lt;/td&gt;&#xA;          &lt;td&gt;安全且零成本&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Go&lt;/td&gt;&#xA;          &lt;td&gt;GC&lt;/td&gt;&#xA;          &lt;td&gt;goroutine（CSP）&lt;/td&gt;&#xA;          &lt;td&gt;静态、结构化接口&lt;/td&gt;&#xA;          &lt;td&gt;编译极快、执行快&lt;/td&gt;&#xA;          &lt;td&gt;简单、工程友好&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;这张表不是为了排座次，没有「最好」的一行，只有「为不同目标做了不同取舍」的若干行。Go 在表里&#xA;的位置，带 GC、CSP 并发、结构化接口、编译极快、设计取向是「简单」，正是它要解决的那些痛&#xA;逼出来的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.2 Go 语言综述</title>
      <link>/zh-cn/part1overview/ch01intro/go/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/zh-cn/part1overview/ch01intro/go/</guid>
      <description>&lt;h1 id=&#34;12-go-语言综述&#34;&gt;1.2 Go 语言综述&lt;/h1&gt;&#xA;&lt;p&gt;这一节为全书搭一个骨架。它不是语法手册，Go 的语法在任何入门书里都讲得清楚，重复它没有意义。&#xA;我们要做的，是先建立一个&lt;strong&gt;俯瞰全局的视角&lt;/strong&gt;：Go 由哪几层构成、它有哪些&lt;strong&gt;与众不同&lt;/strong&gt;的设计决定、&#xA;以及这些决定分别在本书的哪一章展开。读完这一节，再钻进后面任何一章，都不会迷路。&lt;/p&gt;&#xA;&lt;h2 id=&#34;121-三层视角与厚重的运行时&#34;&gt;1.2.1 三层视角与厚重的运行时&lt;/h2&gt;&#xA;&lt;p&gt;理解 Go，可以分三层来看，本书也大致按这三层加上历史铺陈来组织。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;语言层&lt;/strong&gt;，你直接书写的东西：语法、类型系统、并发原语、错误处理。它刻意小而正交，25 个关键字&#xA;就是全部。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;运行时层&lt;/strong&gt;，与你的程序一起被编译进同一个二进制、在背后默默支撑的「小操作系统」：goroutine&#xA;调度器、内存分配器、垃圾回收器、栈管理。这是 Go 最厚重、也最值得剖析的部分。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;工具链层&lt;/strong&gt;，把源码变成可运行、可诊断、可维护程序的机器：编译器、链接器、模块系统、测试与&#xA;可观测性工具。&lt;/p&gt;&#xA;&#xA;&lt;script src=&#34;/mermaid.min.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script src=&#34;/mermaid-init.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&#xA;&lt;pre class=&#34;mermaid&#34;&gt;flowchart TD&#xA;    SRC[&amp;#34;你的 Go 源码&amp;#34;] --&amp;gt;|&amp;#34;编译器 / 链接器&amp;lt;br/&amp;gt;（工具链层，第 3、15、16、17 章）&amp;#34;| BIN&#xA;    BIN[&amp;#34;单个自包含的二进制&amp;lt;br/&amp;gt;内含 runtime（运行时层，第 9–14 章）&amp;#34;] --&amp;gt;|&amp;#34;运行时：调度 goroutine、分配内存、回收垃圾、管理栈&amp;#34;| RUN&#xA;    RUN[&amp;#34;在操作系统线程上并发执行&amp;lt;br/&amp;gt;（语言层语义，第 4–8、10、11 章）&amp;#34;]&#xA;    style BIN fill:#e8f0fe&lt;/pre&gt;&#xA;&lt;p&gt;Go 的一个鲜明特征，是它的&lt;strong&gt;运行时层异常厚重&lt;/strong&gt;。一门 C 程序几乎不带运行时，一门 Java 程序把&#xA;运行时放进一个独立的虚拟机；Go 走的是第三条路，它把调度、垃圾回收、栈管理这些本属操作系统&#xA;范畴的复杂度，&lt;strong&gt;接管进与你的代码一同编译、一同链接的运行时里&lt;/strong&gt;，换取上层的简洁：一个 &lt;code&gt;go&lt;/code&gt;&#xA;关键字就能起一个并发执行、自动内存管理、可在任意深度阻塞的 goroutine。这就是为什么一个 Go&#xA;二进制即便 &lt;code&gt;FROM scratch&lt;/code&gt; 也能独立运行，它自带了一个微型操作系统（这条「自带运行时」的线，&#xA;从 &lt;a href=&#34;../../ch03life/boot&#34;&gt;3.5 启动引导&lt;/a&gt; 一直贯穿到 &lt;a href=&#34;/zh-cn/part4memory/ch14stack/&#34;&gt;14 执行栈&lt;/a&gt;）。&#xA;代价是二进制更大、运行时本身的复杂度可观，但收益是部署极简、并发与内存管理对用户透明。本书&#xA;大半篇幅，正是在剖析这个「藏在二进制里的微型操作系统」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;122-几个与众不同的设计决定&#34;&gt;1.2.2 几个与众不同的设计决定&lt;/h2&gt;&#xA;&lt;p&gt;Go 的气质，集中体现在几个和主流语言不一样的决定上。下面各用一小段代码点出它的样子、指向它在&#xA;本书的归属，并点明它换来了什么、付出了什么。&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.3 顺序进程通讯</title>
      <link>/zh-cn/part1overview/ch01intro/csp/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/zh-cn/part1overview/ch01intro/csp/</guid>
      <description>&lt;h1 id=&#34;13-顺序进程通讯&#34;&gt;1.3 顺序进程通讯&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;本节内容提供一个线上演讲：&lt;a href=&#34;https://www.youtube.com/watch?v=Z8ZpWVuEx8c&#34;&gt;YouTube 在线&lt;/a&gt;，&lt;a href=&#34;https://changkun.de/s/csp/&#34;&gt;Google Slides 讲稿&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Go 并发模型的思想源头，是 Hoare 于 1978 年在 CACM 上提出的&lt;strong&gt;顺序进程通讯&lt;/strong&gt;（Communicating&#xA;Sequential Processes, CSP）。这一节从思想史的角度交代这份血脉，它解释了 goroutine 与&#xA;channel 为何是今天这个样子。channel 与 select 的实现细节（hchan 的环形缓冲、&lt;code&gt;gopark&lt;/code&gt; 与&#xA;&lt;code&gt;goready&lt;/code&gt; 的配对、&lt;code&gt;selectgo&lt;/code&gt; 的两轮加锁），留待 &lt;a href=&#34;../../../part3concurrency/ch10chan/readme&#34;&gt;第 10 章&lt;/a&gt;&#xA;展开；这里关心的是「为什么是 CSP」，以及这份选择如何塑造了 Go 程序的样貌。&lt;/p&gt;&#xA;&lt;h2 id=&#34;131-csp-的核心主张&#34;&gt;1.3.1 CSP 的核心主张&lt;/h2&gt;&#xA;&lt;p&gt;上个世纪七十年代，多核处理器还是科研主题，尚未进入普通程序员的视野。彼时协调并发实体的手段&#xA;已经不少：信号量（Dijkstra, 1965）、监控（Hoare, 1974）、锁与互斥、消息传递。Lauer 与&#xA;Needham 1979 年还证明了「消息传递」与「共享内存加锁」在表达力上彼此等价，二者只是同一件事的&#xA;两副面孔。Hoare 在这片图景里做出的选择，是把通信（即输入输出）当作编程语言的基本要素，并以&#xA;此为唯一的协调手段。&lt;/p&gt;&#xA;&lt;p&gt;CSP 的核心是一句反直觉的主张：&lt;strong&gt;进程之间不共享状态，只通过传递消息来协调。&lt;/strong&gt; 在共享内存的&#xA;世界里，多个线程读写同一块内存，靠锁来防止彼此踩踏，这既危险（数据竞争、死锁），又难以推理。&#xA;CSP 反其道而行：每个顺序进程守着自己的状态，要协作就&lt;strong&gt;发消息&lt;/strong&gt;，通过一次同步的通信动作来交接&#xA;数据与控制权。Go 把这条主张凝成那句广为人知的格言：「&lt;strong&gt;不要以共享内存的方式通信，而要以通信的&#xA;方式共享内存。&lt;/strong&gt;」&lt;/p&gt;&#xA;&lt;p&gt;这里有一处需要澄清的史实，它常被一笔带过，却恰恰是理解 Go 与 CSP 关系的关键。&lt;/p&gt;&#xA;&lt;h2 id=&#34;132-1978-年的-csp按进程名通信没有-channel&#34;&gt;1.3.2 1978 年的 CSP：按进程名通信，没有 channel&lt;/h2&gt;&#xA;&lt;p&gt;读者若翻开 Hoare 1978 年的原始论文，会发现一件出乎意料的事：那门语言里&lt;strong&gt;没有第一类的&#xA;channel&lt;/strong&gt;。通信不是把数据投进某条匿名管道，而是&lt;strong&gt;直接指名某个进程&lt;/strong&gt;。两个基本算符是：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
