<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tony Bai &#187; Vim</title>
	<atom:link href="http://tonybai.com/tag/vim/feed/" rel="self" type="application/rss+xml" />
	<link>https://tonybai.com</link>
	<description>一个程序员的心路历程</description>
	<lastBuildDate>Sun, 12 Apr 2026 22:30:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>“我们放弃了”——Go 团队坦诚布公，聊聊那些可能永远不会加入 Go 的功能</title>
		<link>https://tonybai.com/2025/09/22/go-team-gave-up-on-features/</link>
		<comments>https://tonybai.com/2025/09/22/go-team-gave-up-on-features/#comments</comments>
		<pubDate>Mon, 22 Sep 2025 13:06:02 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AsyncIO]]></category>
		<category><![CDATA[BareMetalGo]]></category>
		<category><![CDATA[BimodalDistribution]]></category>
		<category><![CDATA[CommunityEcosystem]]></category>
		<category><![CDATA[ComplexAPI]]></category>
		<category><![CDATA[ConcurrencySafety]]></category>
		<category><![CDATA[ConcurrencySafetyModel]]></category>
		<category><![CDATA[DamienNeil]]></category>
		<category><![CDATA[DataScience]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOpsScriptingLanguage]]></category>
		<category><![CDATA[DevOps脚本语言]]></category>
		<category><![CDATA[DynamicDetection]]></category>
		<category><![CDATA[Emacs]]></category>
		<category><![CDATA[Embedded]]></category>
		<category><![CDATA[enum]]></category>
		<category><![CDATA[expvar]]></category>
		<category><![CDATA[FilippoValsorda]]></category>
		<category><![CDATA[GeekTime]]></category>
		<category><![CDATA[GenericErrorHandling]]></category>
		<category><![CDATA[genkit]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Go1CompatibilityPromise]]></category>
		<category><![CDATA[Go1兼容性承诺]]></category>
		<category><![CDATA[GoCommunity]]></category>
		<category><![CDATA[GoCoreAdvantages]]></category>
		<category><![CDATA[GoCoreValues]]></category>
		<category><![CDATA[GoEcosystemSplitting]]></category>
		<category><![CDATA[GoEngineeringCapability]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[GoLanguage]]></category>
		<category><![CDATA[GoLanguageAdvancedCourse]]></category>
		<category><![CDATA[GoLanguageFirstCourse]]></category>
		<category><![CDATA[GoPerformance]]></category>
		<category><![CDATA[GopherConEurope2025]]></category>
		<category><![CDATA[gopls]]></category>
		<category><![CDATA[GoProtobuf]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[GoroutineLeakDetection]]></category>
		<category><![CDATA[Goroutine泄漏检测]]></category>
		<category><![CDATA[GoSDK]]></category>
		<category><![CDATA[GoTeamRoundtable]]></category>
		<category><![CDATA[Go团队]]></category>
		<category><![CDATA[Go团队座谈会]]></category>
		<category><![CDATA[Go安全相关]]></category>
		<category><![CDATA[Go工具相关]]></category>
		<category><![CDATA[Go工程化能力]]></category>
		<category><![CDATA[Go性能]]></category>
		<category><![CDATA[Go性能相关]]></category>
		<category><![CDATA[Go核心价值]]></category>
		<category><![CDATA[Go核心优势]]></category>
		<category><![CDATA[Go生态分裂]]></category>
		<category><![CDATA[Go社区]]></category>
		<category><![CDATA[Go设计哲学]]></category>
		<category><![CDATA[Go语言]]></category>
		<category><![CDATA[Go语言第一课]]></category>
		<category><![CDATA[Go语言进阶课]]></category>
		<category><![CDATA[Go运行时]]></category>
		<category><![CDATA[GreenTeaGC]]></category>
		<category><![CDATA[HighReliability]]></category>
		<category><![CDATA[HighSecurityMode]]></category>
		<category><![CDATA[HostEnvironment]]></category>
		<category><![CDATA[ImmutableDataTypes]]></category>
		<category><![CDATA[InteriorPointers]]></category>
		<category><![CDATA[InternalAPI]]></category>
		<category><![CDATA[io_uring]]></category>
		<category><![CDATA[JaneStreet]]></category>
		<category><![CDATA[JonathanAmsterdam]]></category>
		<category><![CDATA[jsonv2]]></category>
		<category><![CDATA[Landlock]]></category>
		<category><![CDATA[LangChain]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[Locality]]></category>
		<category><![CDATA[log/slog]]></category>
		<category><![CDATA[LongTermHealth]]></category>
		<category><![CDATA[math/rand/v2]]></category>
		<category><![CDATA[MCPSDK]]></category>
		<category><![CDATA[MemoryHoles]]></category>
		<category><![CDATA[MichaelPratt]]></category>
		<category><![CDATA[MichaelStapelberg]]></category>
		<category><![CDATA[MultiCore]]></category>
		<category><![CDATA[net/http]]></category>
		<category><![CDATA[net/mail]]></category>
		<category><![CDATA[net/rpc]]></category>
		<category><![CDATA[NixOS]]></category>
		<category><![CDATA[NonNilPointer]]></category>
		<category><![CDATA[NumPy]]></category>
		<category><![CDATA[OAuth2]]></category>
		<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[os.ReadDirFS]]></category>
		<category><![CDATA[Productionization]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Scheduler]]></category>
		<category><![CDATA[Seccomp]]></category>
		<category><![CDATA[SeriousSecurityIssues]]></category>
		<category><![CDATA[ShellScript]]></category>
		<category><![CDATA[shell脚本]]></category>
		<category><![CDATA[StackTrace]]></category>
		<category><![CDATA[standardlibrary]]></category>
		<category><![CDATA[StructAlignmentOptimization]]></category>
		<category><![CDATA[StructFieldOrder]]></category>
		<category><![CDATA[syscall]]></category>
		<category><![CDATA[syslog]]></category>
		<category><![CDATA[Tamago项目]]></category>
		<category><![CDATA[text/tabwriter]]></category>
		<category><![CDATA[TonyBai]]></category>
		<category><![CDATA[UberEngineers]]></category>
		<category><![CDATA[Uber工程师]]></category>
		<category><![CDATA[UnderlyingOptimization]]></category>
		<category><![CDATA[unikernel]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[wasm]]></category>
		<category><![CDATA[不可变数据类型]]></category>
		<category><![CDATA[严重安全问题]]></category>
		<category><![CDATA[内存空洞]]></category>
		<category><![CDATA[内部API]]></category>
		<category><![CDATA[内部指针]]></category>
		<category><![CDATA[动态检测]]></category>
		<category><![CDATA[协程]]></category>
		<category><![CDATA[双峰分布]]></category>
		<category><![CDATA[可扩展性]]></category>
		<category><![CDATA[堆栈跟踪]]></category>
		<category><![CDATA[复杂API]]></category>
		<category><![CDATA[宿主环境]]></category>
		<category><![CDATA[局部性]]></category>
		<category><![CDATA[嵌入式]]></category>
		<category><![CDATA[并发安全]]></category>
		<category><![CDATA[并发安全模型]]></category>
		<category><![CDATA[底层优化]]></category>
		<category><![CDATA[异步IO]]></category>
		<category><![CDATA[数据科学]]></category>
		<category><![CDATA[极客时间]]></category>
		<category><![CDATA[枚举]]></category>
		<category><![CDATA[标准库]]></category>
		<category><![CDATA[死锁]]></category>
		<category><![CDATA[泛型错误处理]]></category>
		<category><![CDATA[生产化]]></category>
		<category><![CDATA[社区生态]]></category>
		<category><![CDATA[结构体字段顺序]]></category>
		<category><![CDATA[结构体对齐优化]]></category>
		<category><![CDATA[裸金属Go]]></category>
		<category><![CDATA[调度器]]></category>
		<category><![CDATA[超多核]]></category>
		<category><![CDATA[长期健康]]></category>
		<category><![CDATA[非Nil指针]]></category>
		<category><![CDATA[高可靠性]]></category>
		<category><![CDATA[高安全模式]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5188</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/09/22/go-team-gave-up-on-features 大家好，我是Tony Bai。 在 GopherCon Europe 2025 的 Go 团队座谈会上，Michael Stapelberg(负责go protobuf)、Damien Neil(负责Go安全相关)、Michael Pratt(负责Go运行时和Go性能相关) 和 Jonathan Amsterdam(log/slog作者，负责Go工具相关) 四位核心成员与社区进行了一场坦诚的对话。他们不仅分享了诸如官方 MCP SDK、“裸金属”Go 等激动人心的进展，更以一种罕见的坦率，正面回应了社区长期以来关心的多个“老大难”问题——包括不可变类型、泛型错误处理和非 nil 指针。其中最引人注目的一句“我们放弃了”，几乎为 Go 语言在某些方向上的演进画上了句号。 本文将带你深入这场座谈会的核心内容，一探 Go 语言的现在与未来。 语言设计的哲学——“不做什么”比“做什么”更重要 座谈会最精彩的部分，莫过于对多个长期存在的语言功能提案的讨论。Go 团队的态度清晰而一致：为了维护 Go 的核心价值——简洁性和易读性，他们愿意对许多看似“美好”的功能说“不”。 不可变数据类型 (immutable) 社区的期待：为 Go 增加类似 immut和const(修饰变量的) 的关键字，以增强代码的安全性和可预测性。 团队的困境：Michael Pratt 承认，这是“可能做的最好的事情之一”，但他紧接着说，“我们不知道该如何实现它”。内部曾有多个提案，但都未成功。核心问题在于，任何这类功能都会像病毒一样在代码库中蔓延，迫使所有 API 都需要考虑 const 和非 const 两种版本，这与 Go 的设计哲学背道而驰。 结论：在社区提出一个绝佳的、能保持语言简洁性的提案之前，官方不会主动推进。 泛型错误处理 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/go-team-gave-up-on-features-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/09/22/go-team-gave-up-on-features">本文永久链接</a> &#8211; https://tonybai.com/2025/09/22/go-team-gave-up-on-features</p>
<p>大家好，我是Tony Bai。</p>
<p>在 GopherCon Europe 2025 的 Go 团队座谈会上，<a href="https://github.com/stapelberg">Michael Stapelberg(负责go protobuf)</a>、<a href="https://github.com/neild">Damien Neil(负责Go安全相关)</a>、<a href="https://github.com/prattmic">Michael Pratt(负责Go运行时和Go性能相关)</a> 和 <a href="https://github.com/jba">Jonathan Amsterdam(log/slog作者，负责Go工具相关)</a> 四位核心成员与社区进行了<a href="https://www.youtube.com/watch?v=etl1Z8T4B9g">一场坦诚的对话</a>。他们不仅分享了诸如<a href="https://tonybai.com/2025/07/10/mcp-official-go-sdk">官方 MCP SDK</a>、<a href="https://tonybai.com/2025/05/13/goos-none-proposal">“裸金属”Go</a> 等激动人心的进展，更以一种罕见的坦率，正面回应了社区长期以来关心的多个“老大难”问题——包括不可变类型、泛型错误处理和非 nil 指针。其中最引人注目的一句“我们放弃了”，几乎为 Go 语言在某些方向上的演进画上了句号。</p>
<p><img src="../BlogImages/2025/go-team-gave-up-on-features-2.png" alt="" /></p>
<p>本文将带你深入这场座谈会的核心内容，一探 Go 语言的现在与未来。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-micro-column-2025-pr.png" alt="" /></p>
<h2>语言设计的哲学——“不做什么”比“做什么”更重要</h2>
<p>座谈会最精彩的部分，莫过于对多个长期存在的语言功能提案的讨论。Go 团队的态度清晰而一致：<strong>为了维护 Go 的核心价值——简洁性和易读性，他们愿意对许多看似“美好”的功能说“不”。</strong></p>
<h3>不可变数据类型 (immutable)</h3>
<ul>
<li><strong>社区的期待</strong>：为 Go 增加类似 immut和const(修饰变量的) 的关键字，以增强代码的安全性和可预测性。</li>
<li><strong>团队的困境</strong>：Michael Pratt 承认，这是“<strong>可能做的最好的事情之一</strong>”，但他紧接着说，“<strong>我们不知道该如何实现它</strong>”。内部曾有多个提案，但都未成功。核心问题在于，任何这类功能都会像病毒一样在代码库中蔓延，迫使所有 API 都需要考虑 const 和非 const 两种版本，这与 Go 的设计哲学背道而驰。</li>
<li><strong>结论</strong>：在社区提出一个绝佳的、能保持语言简洁性的提案之前，官方不会主动推进。</li>
</ul>
<h3>泛型错误处理 (减少 if err != nil)</h3>
<ul>
<li><strong>社区的期待</strong>：引入 try/check 等机制，减少错误处理的冗余代码。</li>
<li><strong>团队的“投降”</strong>：在经过长达数年的思考和无数次讨论后，Go团队给出了一个<a href="https://tonybai.com/2025/06/04/error-syntax">爆炸性的结论</a>：“<strong>我们放弃了 (we give up)。</strong>” 团队承认，他们找不到任何一种能让所有人都满意的、既能减少冗余又不损失清晰性的方法。</li>
<li><strong>新的焦点</strong>：这一“投降”反而让团队感到“极度兴奋”。因为它意味着可以停止在“冗余”这个问题上内耗，转而思考其他更重要的错误处理问题。Damien 明确指出，<strong>如何在错误中加入堆栈跟踪</strong>才是当前错误处理最大的痛点，也是团队更愿意投入精力去探索的方向。</li>
</ul>
<h3>非 Nil 指针 (non-nil)</h3>
<ul>
<li><strong>社区的期待</strong>：通过语言机制在编译期防止 nil 指针解引用。</li>
<li><strong>团队的权衡</strong>：Jonathan Amsterdam 解释道，虽然非 nil 指针很好，但它会引入两种指针类型，让一切都变成两倍。或者需要引入复杂的流式类型分析，这会使代码更难阅读和理解。</li>
<li><strong>一个反直觉的洞见</strong>：“<strong>Nil 指针错误是最好的运行时错误</strong>”，因为它有确定性的堆栈跟踪，易于定位。团队更关心那些非确定性的、只在生产环境中出现的并发 bug，比如 goroutine 泄漏。</li>
</ul>
<h3>枚举 (enum)</h3>
<ul>
<li><strong>社区的期待</strong>：提供比 iota 更强大、更类型安全的枚举支持。</li>
<li><strong>团队的困惑</strong>：Damien 指出，社区对 enum 的需求至少有两种截然不同的解读：一种是“整数的枚举”，另一种是“类型的枚举”（即代数数据类型），两者差异巨大。在社区就“到底想要什么”达成共识之前，团队很难推进。</li>
</ul>
<h2>标准库的“新陈代谢”——演进、维护与“瘦身”</h2>
<p>标准库是 Go 生态的基石，但随着时间的推移，一些包也显现出历史的痕迹。</p>
<h3>哪些包应该被“移除”？</h3>
<p>团队成员们“点名”了一些他们认为设计不佳或已不再主流的包：</p>
<ul>
<li>text/tabwriter: Damien 认为其设计不佳，如果现在重来，会做一个 v2 版本。</li>
<li><strong>运行时的诊断(diagnostic) API</strong>: Michael Pratt 认为现有的 API “有点陈旧，难以使用”，希望能有更好的 API，但不确定是否值得为此做一个 v2。</li>
<li>net/rpc: 被 gRPC 全面超越。</li>
<li>expvar: 非常小众，很少有人使用。</li>
<li>syscall: 正在被 golang.org/x/sys 逐步取代，以实现更灵活的更新。</li>
<li>net/mail, syslog: 社区已经有了功能更强大、更受青睐的替代方案，标准库的实现已沦为“鸡肋”。</li>
</ul>
<p>虽然因为 Go 1 的兼容性承诺无法真正移除它们，但团队的态度表明，未来的发展重心将不会在这些包上。</p>
<h3>拥抱 v2，但极其审慎</h3>
<p><a href="https://tonybai.com/2025/05/15/go-json-v2/">json/v2</a> 和 math/rand/v2 的出现，标志着 Go 团队愿意为那些存在根本性设计缺陷的包创建 v2 版本。但团队强调，这是一个<strong>极为例外</strong>的手段，只有在“<strong>现有 API 框架内无法做出改进</strong>”时才会考虑，因为 v2 会带来生态的分裂和迁移成本。</p>
<h2>Go 在新时代的定位与机遇</h2>
<p>面对 AI、裸金属(bare metal)等新兴领域，Go 将如何定位自己？</p>
<h3>Go 在 AI 与数据科学领域的角色</h3>
<ul>
<li><strong>清晰的边界</strong>：Go 团队不会去开发一个与 LangChain 或 Genkit 竞争的官方 AI 框架，也不会深入数值计算（社区的 gonum 已经很出色）。</li>
<li><strong>专注“生产化” (Productionization)</strong>：团队认为，Go 的核心优势在于将 Python 中训练和设计的模型，<strong>部署到高性能、高并发的生产环境中</strong>。这是 Go 想要“拥有”的领域。Jonathan Amsterdam 更是直言：“你用 numpy 把东西搭起来，但你不会想用 Python 把它部署到生产环境。这时候你就该用 Go 了。”</li>
<li><strong>提供核心 SDK 支持</strong>：团队将致力于为重要的 AI 规范和平台（如 MCP, Gemini, Genkit）提供<a href="https://tonybai.com/2025/07/10/mcp-official-go-sdk/">高质量的官方 Go SDK</a>。</li>
</ul>
<h3>“裸金属” Go (Bare metal Go)</h3>
<ul>
<li><strong>进展</strong>：Michael Pratt 确认，<a href="https://tonybai.com/2025/05/13/goos-none-proposal">一项由 Tamago 项目推动的新提案正在讨论中</a>，旨在为 Go 运行时提供一个更稳定的内部 API，使其能更好地与底层系统交互。</li>
<li><strong>价值</strong>：这将使 Go 在嵌入式、unikernel 等领域的应用变得更加容易，并且其设计是通用的，不局限于特定 CPU 架构。</li>
</ul>
<h2>激动人心的地平线——运行时与工具链的前沿探索</h2>
<p>座谈会也透露了几个正在进行中的、令人兴奋的底层项目：</p>
<ul>
<li><strong>官方 MCP SDK</strong>：Jonathan Amsterdam 确认，官方的 <a href="https://github.com/modelcontextprotocol/go-sdk">Go MCP SDK</a> 随时可能发布正式版，它吸取了社区现有实现的经验，设计更清晰，旨在成为官方标准。</li>
<li><strong>Green Tea GC</strong>：Michael Pratt 提到，Michael Knyszek 正在进行一项名为“Green Tea”的 GC 改进提案，旨在提升 GC 在超多核（如 256 核）机器上的<strong>可扩展性和局部性 (locality)</strong>，以应对现代服务器硬件的发展。</li>
<li><strong>Goroutine 泄漏检测</strong>：团队正在与 Uber 的工程师合作，计划将一项<a href="https://tonybai.com/2025/07/24/deadlock-detection-by-gc">利用 GC 来动态检测部分死锁（即 goroutine 泄漏）的技术</a>引入 Go。这项技术能找出那些“永远等待”在一个无人能触及的 channel 上的 goroutine，并将其报告出来。</li>
<li><strong>WASM 的原生 GC 集成</strong>：团队希望未来能让 Go 编译的 WebAssembly 使用宿主环境（如浏览器）的原生 GC，但这面临着 Go 严重依赖“内部指针”（interior pointers）而 WASM GC 不支持的巨大技术挑战。</li>
<li><strong>结构体对齐优化</strong>：David Chase 正在推动一个“个人激情项目”，目标是让编译器<strong>自动优化结构体字段的顺序</strong>，以减少内存空洞和提高空间效率。未来开发者将不再需要手动调整字段顺序。相关的提示功能已在 gopls 中提供。</li>
</ul>
<h2>开发者的日常——工具、协作与社区</h2>
<p>座谈会的最后，团队成员分享了他们作为开发者的工作日常和对社区的看法。</p>
<ul>
<li><strong>AI 工具的使用</strong>：团队成员普遍开始使用 LLM。Jonathan Amsterdam 发现它是学习 OAUTH2 这类复杂规范的“极有耐心的老师”；Michael Stapelberg 则用它来学习 NixOS。Damien 更是认为 LLM 在处理 Go 代码时表现出色，因为 Go 的简洁性和向后兼容性为模型提供了高质量的训练数据。</li>
<li><strong>编辑器之争</strong>：Michael Stapelberg 坦诚自己已从 Vim 叛逃至 Emacs，引发了现场的善意哄笑。</li>
<li><strong>对 Go 社区的信心</strong>：当被问及“如果 Google 不再支持 Go，社区能否接手”时，团队成员们毫不犹豫地表示肯定。他们认为 Go 社区非常强大且自给自足，拥有大量非 Google 的核心贡献者（并以 Filippo Valsorda 为例），社区的繁荣并不完全依赖于 Google。</li>
</ul>
<h2>拾遗——关于性能、安全与其他语言的思考</h2>
<p>除了上述重大议题，座谈会还触及了许多开发者关心的具体问题，这些简短的问答同样充满了来自 Go 团队的深刻洞见。</p>
<h3>Go 与 Rust：灵感的源泉</h3>
<p>当被问及对 Rust 等其他语言的看法时，团队表现出开放和欣赏的态度。</p>
<ul>
<li><strong>并发安全</strong>：Jonathan Amsterdam 坦言，Rust 提供的并发安全模型是他们“都希望在 Go 中拥有”的东西，因为它能极大地提升程序的可靠性。但他同时指出，在不让 Go 变得像 Rust 一样复杂的前提下，目前还没有找到实现路径。</li>
<li><strong>不同的演进道路</strong>：团队也关注 OCaml 在并发安全上的探索。Jane Street 采用了一种与 Rust 完全不同的方法来实现并发安全，这表明解决同一问题可以有多条路径，Go 也在持续观察和学习。</li>
</ul>
<h3>性能：一个“双峰分布”的社区</h3>
<p>Michael Pratt 对 Go 的性能有一个有趣的观察，他认为社区对此的感受呈现“双峰分布”：</p>
<ul>
<li><strong>一端是极其满意的用户</strong>：他们可能从 Python 等动态语言迁移而来，享受到了数十倍的性能提升，对现状非常满意。</li>
<li><strong>另一端是要求极致性能的用户</strong>：大厂在海量部署下，对性能的渴求永无止境，任何微小的优化都能带来巨大的成本节约。</li>
</ul>
<p>Go 团队的性能优化工作，主要聚焦于服务后一类用户，例如 json/v2、<a href="https://tonybai.com/2024/11/14/go-map-use-swiss-table">新的 map 实现</a>以及 <a href="https://tonybai.com/2025/05/03/go-green-tea-garbage-collector/">Green Tea GC</a>。</p>
<h3>安全：API 优于“模式开关”</h3>
<p>对于“能否为 Go 增加一个‘高安全模式’开关”的问题，团队更倾向于通过<strong>改进 API</strong> 来解决安全问题。</p>
<ul>
<li>**Damien ** 提到，一个可能的方向是为 net/http 包增加一个“高安全服务器”标志，该标志将启用一系列更安全的默认配置（例如，更严格的超时），以修正十年前设定的一些已过时的默认值。</li>
<li><strong>Michael Stapelberg</strong> 补充道，Go 已经提供了像 os.ReadDirFS 这样更安全的路径遍历 API，并且 Go 程序与 Seccomp、Landlock 等 Linux 沙箱技术能很好地集成。从 API 和系统层面入手，是比引入一个全局的、模糊的“安全模式”更精细、更合理的做法。</li>
</ul>
<h3>io_uring：令人兴奋但为时过早</h3>
<p>对于 Linux 下备受瞩的 io_uring，Michael Stapelberg 表达了谨慎的乐观。他承认 io_uring 性能惊人，但其复杂的 API 和过去暴露出的<strong>严重安全问题</strong>，使得 Google 内部服务器完全禁用了该功能。他认为，在它变得更成熟、更安全之前，<a href="https://tonybai.com/2025/08/11/why-go-not-embrace-iouring">考虑将其大规模引入 Go 还为时过早</a>。此外，Michael Pratt 补充说，Go 的运行时和调度器已经通过 goroutine 隐藏了大部分 I/O 异步的复杂性，因此 io_uring 能带来的部分核心优势，Go 已经通过不同的方式实现了。</p>
<h3>Go 作为 DevOps 脚本语言</h3>
<p>当被问及 Go 能否取代 Python 成为 DevOps 脚本语言时，团队成员们几乎异口同声地表示：<strong>“在 Google 内部，这已经发生了。”</strong> Michael Stapelberg 分享说，他自己现在会避免编写任何中等复杂度的 shell 脚本，而是直接从 Go 开始，因为 Go 的强类型和工程化能力，能避免脚本在变复杂后迅速变得难以维护。</p>
<h2>小结：一个务实、专注且充满活力的 Go</h2>
<p>这场座谈会向我们展示了一个成熟、务实的 Go 团队。他们不再试图让 Go 成为解决所有问题的“瑞士军刀”，而是更加专注于其核心优势：<strong>简洁性、高性能、以及在构建大规模、高可靠性生产系统方面的卓越能力。</strong></p>
<p>他们愿意为了保持语言的长期健康而对一些“美好”的功能说“不”，也乐于承认在某些领域的探索（如错误处理冗余）已经走到了尽头。但与此同时，他们也在积极地拥抱新的机遇（如 AI 生产化），并从底层（GC、运行时）不断地进行着深刻的、影响深远的优化。</p>
<p>正如 Michael Stapelberg 所言，Go 社区是如此强大和自给自足，以至于团队的参与有时并非决定性的。这或许是对 Go 这门语言及其社区生态成熟度的最高赞誉。</p>
<p>视频链接：https://www.youtube.com/watch?v=etl1Z8T4B9g</p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p><strong>想系统学习Go，构建扎实的知识体系？</strong></p>
<p>我的新书《<a href="https://book.douban.com/subject/37499496/">Go语言第一课</a>》是你的首选。源自2.4万人好评的极客时间专栏，内容全面升级，同步至Go 1.24。首发期有专属五折优惠，不到40元即可入手，扫码即可拥有这本300页的Go语言入门宝典，即刻开启你的Go语言高效学习之旅！</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-primer-published-4.png" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/09/22/go-team-gave-up-on-features/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go写业务是垃圾？Rust重写是坨屎？聊聊程序员评论区里的那股“煞气”</title>
		<link>https://tonybai.com/2025/09/19/the-tension-in-programmer-comments/</link>
		<comments>https://tonybai.com/2025/09/19/the-tension-in-programmer-comments/#comments</comments>
		<pubDate>Fri, 19 Sep 2025 00:10:06 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Emacs]]></category>
		<category><![CDATA[GC问题]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go1.24]]></category>
		<category><![CDATA[Gopher]]></category>
		<category><![CDATA[Go语言第一课]]></category>
		<category><![CDATA[MAC]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[Rustacean]]></category>
		<category><![CDATA[TonyBai]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[WebAssembly]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[“煞评”]]></category>
		<category><![CDATA[上下文]]></category>
		<category><![CDATA[专栏]]></category>
		<category><![CDATA[业务]]></category>
		<category><![CDATA[严谨]]></category>
		<category><![CDATA[事实]]></category>
		<category><![CDATA[二元对立]]></category>
		<category><![CDATA[优越感]]></category>
		<category><![CDATA[信仰]]></category>
		<category><![CDATA[光]]></category>
		<category><![CDATA[入门宝典]]></category>
		<category><![CDATA[公众号]]></category>
		<category><![CDATA[共同努力]]></category>
		<category><![CDATA[内容创作者]]></category>
		<category><![CDATA[净化]]></category>
		<category><![CDATA[分 享者]]></category>
		<category><![CDATA[创作者]]></category>
		<category><![CDATA[初学时期]]></category>
		<category><![CDATA[助推者]]></category>
		<category><![CDATA[化解]]></category>
		<category><![CDATA[匿名]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[压力]]></category>
		<category><![CDATA[受害者]]></category>
		<category><![CDATA[同理心]]></category>
		<category><![CDATA[吐槽]]></category>
		<category><![CDATA[喷子]]></category>
		<category><![CDATA[困惑]]></category>
		<category><![CDATA[基石]]></category>
		<category><![CDATA[复杂性]]></category>
		<category><![CDATA[大规模分布式系统]]></category>
		<category><![CDATA[存在价值]]></category>
		<category><![CDATA[小型项目]]></category>
		<category><![CDATA[工程背景]]></category>
		<category><![CDATA[工程问题]]></category>
		<category><![CDATA[建设]]></category>
		<category><![CDATA[建设性]]></category>
		<category><![CDATA[建设性批评]]></category>
		<category><![CDATA[微服务]]></category>
		<category><![CDATA[心理动因]]></category>
		<category><![CDATA[思想]]></category>
		<category><![CDATA[思想碰撞]]></category>
		<category><![CDATA[思维惯性]]></category>
		<category><![CDATA[情绪]]></category>
		<category><![CDATA[情绪宣泄]]></category>
		<category><![CDATA[情绪投射]]></category>
		<category><![CDATA[戾气]]></category>
		<category><![CDATA[执念]]></category>
		<category><![CDATA[技术世界]]></category>
		<category><![CDATA[技术圣战]]></category>
		<category><![CDATA[技术方向]]></category>
		<category><![CDATA[技术社区]]></category>
		<category><![CDATA[技术观点]]></category>
		<category><![CDATA[技术讨论]]></category>
		<category><![CDATA[技术进步]]></category>
		<category><![CDATA[技术选型]]></category>
		<category><![CDATA[技术部落主义]]></category>
		<category><![CDATA[抽象能力]]></category>
		<category><![CDATA[挣扎]]></category>
		<category><![CDATA[挫败感]]></category>
		<category><![CDATA[探索]]></category>
		<category><![CDATA[操作系统]]></category>
		<category><![CDATA[攻击性]]></category>
		<category><![CDATA[放大效应]]></category>
		<category><![CDATA[断言大师]]></category>
		<category><![CDATA[新人]]></category>
		<category><![CDATA[智慧]]></category>
		<category><![CDATA[替代方案]]></category>
		<category><![CDATA[最优解]]></category>
		<category><![CDATA[权衡]]></category>
		<category><![CDATA[权衡考量]]></category>
		<category><![CDATA[来源]]></category>
		<category><![CDATA[极客时间]]></category>
		<category><![CDATA[架构]]></category>
		<category><![CDATA[框架]]></category>
		<category><![CDATA[正确]]></category>
		<category><![CDATA[源码]]></category>
		<category><![CDATA[煞气]]></category>
		<category><![CDATA[珍视]]></category>
		<category><![CDATA[理性]]></category>
		<category><![CDATA[病毒]]></category>
		<category><![CDATA[知识体系]]></category>
		<category><![CDATA[知识储备]]></category>
		<category><![CDATA[知识的局限性]]></category>
		<category><![CDATA[知识的诅咒]]></category>
		<category><![CDATA[社交约束]]></category>
		<category><![CDATA[社区修行]]></category>
		<category><![CDATA[祥和之气]]></category>
		<category><![CDATA[秀优越]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[精神家园]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[编辑器]]></category>
		<category><![CDATA[网络匿名性]]></category>
		<category><![CDATA[网络评论区]]></category>
		<category><![CDATA[观点]]></category>
		<category><![CDATA[讨论]]></category>
		<category><![CDATA[讨论氛围]]></category>
		<category><![CDATA[论据]]></category>
		<category><![CDATA[评论区]]></category>
		<category><![CDATA[语言]]></category>
		<category><![CDATA[读者]]></category>
		<category><![CDATA[谦逊]]></category>
		<category><![CDATA[负面情绪]]></category>
		<category><![CDATA[质疑]]></category>
		<category><![CDATA[资历]]></category>
		<category><![CDATA[资格论]]></category>
		<category><![CDATA[资深开发者]]></category>
		<category><![CDATA[身份]]></category>
		<category><![CDATA[身份认同]]></category>
		<category><![CDATA[软件开发]]></category>
		<category><![CDATA[辩论]]></category>
		<category><![CDATA[逻辑]]></category>
		<category><![CDATA[部落主义]]></category>
		<category><![CDATA[风险]]></category>
		<category><![CDATA[驱散]]></category>
		<category><![CDATA[高认知负荷]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5178</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/09/19/the-tension-in-programmer-comments 大家好，我是Tony Bai。 做公众号/博客这些年，我收到了成千上万条来自程序员朋友的评论。绝大多数都充满了智慧、好奇和善意，正是这些交流，构成了我持续分享的最大动力。但与此同时，我也常常在评论区里，感受到一股强烈的、带有攻击性的无形之气。 比如，当我分享一篇关于Go在业务场景实践的文章时，总会有人跳出来，言简意赅地留下一句：“用Go写业务是不是很垃圾？” 又比如，当社区在探讨用Rust重构某个C++项目时，评论区可能会出现这样的“高论”：“用Rust重写C++代码，就是从一坨屎变成了另一坨屎。” 这些评论，往往脏字当头，不带任何论据，纯粹是情绪的宣泄。我思来想去，觉得用“戾气”或“喷子”来形容，似乎都不够精准。直到有一天，一个词蹦进了我的脑海——“煞气”。 这个词，源于传统文化，意指一种凶戾、非理性、具有破坏性的气场。它精准地捕捉了这类评论的本质：其目的并非交流思想，而是用情绪的冲击波，扼杀讨论，打击分享者的热情。正因如此，我之前公众号的自动精选评论和留言不得不改为手工精选，这不仅增加了工作量，还降低了评论展示的及时性。 今天，这篇文章不旨在批判，而是想和大家一起，深入地聊一聊程序员评论区里的这股“煞气”，尝试理解它从何而来，并探讨作为技术社区的一员，我们该如何面对它，如何保护我们共同的精神家园。 “煞气”的百态图鉴：你一定见过的几种典型“煞评” 这股“煞气”并非铁板一块，它以多种面目出现在我们的视野中，总有一种让你觉得似曾相识： “一言以蔽之”型 这类评论堪称“断言大师”，从不屑于提供论据，仅用一句话便能给一门语言、一个框架甚至一个技术方向盖棺定论。 “Go就是不行。” “WebAssembly没前途。” “微服务就是个坑。” 简洁，有力，不容置疑，仿佛掌握了宇宙的终极真理。 “非黑即白”型（技术圣战） 在他们眼中，技术选型不是基于场景和权衡，而是一场关乎信仰的“圣战”。语言、编辑器、操作系统……万物皆可站队，异端必须被消灭。 “用Rust重写C++就是从一坨屎变成另一坨屎。” “Vim/Emacs之外皆异端！” “还在用Windows/Mac开发？笑死。” “资格论”与“秀优越”型 这类评论善于通过攻击对方的身份、资历或知识储备，来釜底抽薪式地否定其观点，从而建立自己的优越感。 “你连源码都没读过，凭什么评论？” “这东西我十年前就玩过了，没什么新意。” “等你写到百万行代码再来讨论架构吧。” “情绪投射”型 这类评论者，往往将自己在工作中因某项技术受挫而产生的负面情绪，无差别地投射到所有相关的公开讨论中，把评论区当成了情绪的垃圾桶。 “我们项目刚被XXX坑惨了，这玩意儿就是个彻头彻尾的垃圾！” “又在吹这门语言？我刚因为它的GC问题加了三天班！” 这些充满“煞气”的评论，像病毒一样侵蚀着技术社区的讨论氛围，让许多乐于分享的创作者心生寒意，也让许多渴望学习的新人望而却步。 溯源“煞气”：它们究竟从何而来？ 要应对“煞气”，首先要理解它的来源。它并非简单的“素质问题”，背后往往有更深层次的、属于程序员群体的心理动因： 高认知负荷与挫败感： 软件开发本质上是一项与复杂性搏斗的高难度、高挫败感的工作。代码不工作是常态，被需求反复折磨是日常。长期累积的压力和挫败感，需要一个宣泄的出口，而匿名的网络评论区便成了最廉价的选择。 强身份认同与技术部落主义： 许多程序员倾向于将自我价值与所掌握的技术栈深度绑定。“我是Gopher”、“我是Rustacean”，这种身份认同感带来了归属感，但也催生了“部落主义”。攻击对立的技术，本质上是在捍卫自我身份和所属部落的“荣耀”。 对“最优解”的执念与抽象能力的差异： 我们的工作是与逻辑打交道，追求严谨和正确，这使得许多程序员潜意识里相信存在一个放之四海而皆准的“最优解”。这种思维惯性，导致在面对需要权衡（Trade-off）的工程问题时，容易陷入“非黑即白”的二元对立，无法容忍不同场景下的不同选择。 知识的诅咒： 一些资深开发者，已经忘记了自己初学时期的困惑和挣扎。他们对自己领域内“显而易见”的知识缺乏同理心，容易将新手的提问或不成熟的观点视为“愚蠢”，并报以轻蔑或不耐烦。 网络匿名性的放大效应： 这是所有网络社区的通病。脱离了现实世界的社交约束，人们更容易释放出内心的攻击性。 化解“煞气”：我们每个人的社区修行 面对弥漫的“煞气”，无论是内容创作者还是普通读者，我们每个人都身处其中，既可能是受害者，也可能在不经意间成为助推者。与其抱怨环境，不如从自身做起，共同参与到社区的净化与建设中来。 给所有社区参与者的“修行建议”： 评论前，区分“观点”与“情绪”： 在敲下键盘前，花一秒钟审视内心：我即将表达的，是基于逻辑和事实的技术观点，还是仅仅是想吐槽一下今天遇到的某个Bug或者糟糕的心情？有意识地分离这两者，是理性讨论的第一步。 拥抱“建设性批评”的艺术： 如果你不同意某个观点，这非常正常，甚至是技术进步的源泉。但请尝试用建设性的方式来表达： 提供论据： “我认为这个方案有风险，因为在XX场景下，它可能会导致YY问题。” [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/the-tension-in-programmer-comments-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/09/19/the-tension-in-programmer-comments">本文永久链接</a> &#8211; https://tonybai.com/2025/09/19/the-tension-in-programmer-comments</p>
<p>大家好，我是Tony Bai。</p>
<p>做公众号/博客这些年，我收到了成千上万条来自程序员朋友的评论。绝大多数都充满了智慧、好奇和善意，正是这些交流，构成了我持续分享的最大动力。但与此同时，我也常常在评论区里，感受到一股强烈的、带有攻击性的无形之气。</p>
<p>比如，当我分享一篇关于Go在业务场景实践的文章时，总会有人跳出来，言简意赅地留下一句：“用Go写业务是不是很垃圾？”</p>
<p>又比如，当社区在探讨用Rust重构某个C++项目时，评论区可能会出现这样的“高论”：“用Rust重写C++代码，就是从一坨屎变成了另一坨屎。”</p>
<p>这些评论，往往脏字当头，不带任何论据，纯粹是情绪的宣泄。我思来想去，觉得用“戾气”或“喷子”来形容，似乎都不够精准。直到有一天，一个词蹦进了我的脑海——<strong>“煞气”</strong>。</p>
<p>这个词，源于传统文化，意指一种凶戾、非理性、具有破坏性的气场。它精准地捕捉了这类评论的本质：其目的并非交流思想，而是用情绪的冲击波，扼杀讨论，打击分享者的热情。正因如此，我之前公众号的自动精选评论和留言不得不改为手工精选，这不仅增加了工作量，还降低了评论展示的及时性。</p>
<p>今天，这篇文章不旨在批判，而是想和大家一起，<strong>深入地聊一聊程序员评论区里的这股“煞气”，尝试理解它从何而来，并探讨作为技术社区的一员，我们该如何面对它，如何保护我们共同的精神家园。</strong></p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-micro-column-2025-pr.png" alt="" /></p>
<h2>“煞气”的百态图鉴：你一定见过的几种典型“煞评”</h2>
<p>这股“煞气”并非铁板一块，它以多种面目出现在我们的视野中，总有一种让你觉得似曾相识：</p>
<ul>
<li>
<p><strong>“一言以蔽之”型</strong><br />
这类评论堪称“断言大师”，从不屑于提供论据，仅用一句话便能给一门语言、一个框架甚至一个技术方向盖棺定论。</p>
<ul>
<li><em>“Go就是不行。”</em></li>
<li><em>“WebAssembly没前途。”</em></li>
<li><em>“微服务就是个坑。”</em><br />
简洁，有力，不容置疑，仿佛掌握了宇宙的终极真理。</li>
</ul>
</li>
<li>
<p><strong>“非黑即白”型（技术圣战）</strong><br />
在他们眼中，技术选型不是基于场景和权衡，而是一场关乎信仰的“圣战”。语言、编辑器、操作系统……万物皆可站队，异端必须被消灭。</p>
<ul>
<li><em>“用Rust重写C++就是从一坨屎变成另一坨屎。”</em></li>
<li><em>“Vim/Emacs之外皆异端！”</em></li>
<li><em>“还在用Windows/Mac开发？笑死。”</em></li>
</ul>
</li>
<li>
<p><strong>“资格论”与“秀优越”型</strong><br />
这类评论善于通过攻击对方的身份、资历或知识储备，来釜底抽薪式地否定其观点，从而建立自己的优越感。</p>
<ul>
<li><em>“你连源码都没读过，凭什么评论？”</em></li>
<li><em>“这东西我十年前就玩过了，没什么新意。”</em></li>
<li><em>“等你写到百万行代码再来讨论架构吧。”</em></li>
</ul>
</li>
<li>
<p><strong>“情绪投射”型</strong><br />
这类评论者，往往将自己在工作中因某项技术受挫而产生的负面情绪，无差别地投射到所有相关的公开讨论中，把评论区当成了情绪的垃圾桶。</p>
<ul>
<li><em>“我们项目刚被XXX坑惨了，这玩意儿就是个彻头彻尾的垃圾！”</em></li>
<li><em>“又在吹这门语言？我刚因为它的GC问题加了三天班！”</em></li>
</ul>
</li>
</ul>
<p>这些充满“煞气”的评论，像病毒一样侵蚀着技术社区的讨论氛围，让许多乐于分享的创作者心生寒意，也让许多渴望学习的新人望而却步。</p>
<h2>溯源“煞气”：它们究竟从何而来？</h2>
<p>要应对“煞气”，首先要理解它的来源。它并非简单的“素质问题”，背后往往有更深层次的、属于程序员群体的心理动因：</p>
<ol>
<li><strong>高认知负荷与挫败感：</strong> 软件开发本质上是一项与复杂性搏斗的高难度、高挫败感的工作。代码不工作是常态，被需求反复折磨是日常。长期累积的压力和挫败感，需要一个宣泄的出口，而匿名的网络评论区便成了最廉价的选择。</li>
<li><strong>强身份认同与技术部落主义：</strong> 许多程序员倾向于将自我价值与所掌握的技术栈深度绑定。“我是Gopher”、“我是Rustacean”，这种身份认同感带来了归属感，但也催生了“部落主义”。攻击对立的技术，本质上是在捍卫自我身份和所属部落的“荣耀”。</li>
<li><strong>对“最优解”的执念与抽象能力的差异：</strong> 我们的工作是与逻辑打交道，追求严谨和正确，这使得许多程序员潜意识里相信存在一个放之四海而皆准的“最优解”。这种思维惯性，导致在面对需要权衡（Trade-off）的工程问题时，容易陷入“非黑即白”的二元对立，无法容忍不同场景下的不同选择。</li>
<li><strong>知识的诅咒：</strong> 一些资深开发者，已经忘记了自己初学时期的困惑和挣扎。他们对自己领域内“显而易见”的知识缺乏同理心，容易将新手的提问或不成熟的观点视为“愚蠢”，并报以轻蔑或不耐烦。</li>
<li><strong>网络匿名性的放大效应：</strong> 这是所有网络社区的通病。脱离了现实世界的社交约束，人们更容易释放出内心的攻击性。</li>
</ol>
<h2>化解“煞气”：我们每个人的社区修行</h2>
<p>面对弥漫的“煞气”，无论是内容创作者还是普通读者，我们每个人都身处其中，既可能是受害者，也可能在不经意间成为助推者。与其抱怨环境，不如从自身做起，共同参与到社区的净化与建设中来。</p>
<p><strong>给所有社区参与者的“修行建议”：</strong></p>
<ol>
<li><strong>评论前，区分“观点”与“情绪”：</strong> 在敲下键盘前，花一秒钟审视内心：我即将表达的，是基于逻辑和事实的技术观点，还是仅仅是想吐槽一下今天遇到的某个Bug或者糟糕的心情？有意识地分离这两者，是理性讨论的第一步。</li>
<li><strong>拥抱“建设性批评”的艺术：</strong> 如果你不同意某个观点，这非常正常，甚至是技术进步的源泉。但请尝试用建设性的方式来表达：
<ul>
<li><strong>提供论据：</strong> “我认为这个方案有风险，因为在XX场景下，它可能会导致YY问题。”</li>
<li><strong>提供替代方案：</strong> “相比A方案，我更推荐B方案，因为B在处理XX方面更有优势。”</li>
<li><strong>补充上下文：</strong> “这个观点在小型项目中可能适用，但在大规模分布式系统中，我们需要额外考虑……”<br />
这样的评论，远比一句简单的“你这是垃圾”有价值千万倍。</li>
</ul>
</li>
<li><strong>常怀谦逊与同理心：</strong> 技术世界浩瀚无垠，我们每个人都只是其中渺小的一粟。承认自己知识的局限性，尊重不同技术在不同场景下的存在价值。我们今天所不屑的，可能正是我们昨天所困惑的；我们今天所熟稔的，可能是别人明天将要探索的新大陆。多一份同理心，少一份优越感。</li>
</ol>
<h2>小结：化“煞气”为“祥和之气”，共建更有价值的技术社区</h2>
<p>回到开头的那些评论。Go写业务当然不是垃圾，Rust重写C++也绝非原地踏步。每一种技术选择背后，都有其复杂的工程背景和权衡考量。一个健康的技术社区，应该是一个能够容纳并理性探讨这些权衡的地方。</p>
<p>我们探讨“程序员的‘煞气’”，目标不是消灭所有反对的声音，健康的质疑和辩论是技术进步的基石。我们的目标，是希望将那些无意义的、纯粹消耗热情的情绪宣泄，转化为能够推动我们共同进步的思想碰撞。</p>
<p>这需要我们每一位社区参与者的共同努力：分享者多一份对人性的理解和对经验的珍视，评论者多一份理性和建设性的态度。</p>
<p>愿我们都能成为驱散“煞气”的光，让技术社区的每一次讨论，都离智慧更近一步。</p>
<hr />
<p><strong>想系统学习Go，构建扎实的知识体系？</strong></p>
<p>我的新书《<a href="https://book.douban.com/subject/37499496/">Go语言第一课</a>》是你的首选。源自2.4万人好评的极客时间专栏，内容全面升级，同步至Go 1.24。首发期有专属五折优惠，不到40元即可入手，扫码即可拥有这本300页的Go语言入门宝典，即刻开启你的Go语言高效学习之旅！</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-primer-published-4.png" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/09/19/the-tension-in-programmer-comments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Anthropic内部实践首次公开：揭秘Claude Code如何引爆全员生产力</title>
		<link>https://tonybai.com/2025/07/25/how-anthropic-teams-use-claude-code/</link>
		<comments>https://tonybai.com/2025/07/25/how-anthropic-teams-use-claude-code/#comments</comments>
		<pubDate>Fri, 25 Jul 2025 13:46:56 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Anthropic]]></category>
		<category><![CDATA[Claude.md]]></category>
		<category><![CDATA[ClaudeCode]]></category>
		<category><![CDATA[GEMINI.md]]></category>
		<category><![CDATA[GeminiCli]]></category>
		<category><![CDATA[infra]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[monorepo]]></category>
		<category><![CDATA[openai]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[TS]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[人工智能]]></category>
		<category><![CDATA[代码库]]></category>
		<category><![CDATA[基础设施]]></category>
		<category><![CDATA[大模型]]></category>
		<category><![CDATA[并行]]></category>
		<category><![CDATA[强化学习]]></category>
		<category><![CDATA[文档]]></category>
		<category><![CDATA[智能体]]></category>
		<category><![CDATA[机器学习]]></category>
		<category><![CDATA[注释]]></category>
		<category><![CDATA[测试]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[编码]]></category>
		<category><![CDATA[设计]]></category>
		<category><![CDATA[调试]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4954</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/07/25/how-anthropic-teams-use-claude-code 当 AI 编程助手从简单的代码补全工具，演变为深度集成于开发者工作流核心的“终端原生 AI”（Terminal-native AI）时，一个根本性的问题浮现出来：顶尖团队究竟是如何在日常工作中驾驭这股新力量的？ 理论和演示层出不穷，但真实、大规模、跨职能的实践案例却凤毛麟角。 现在，我们得到了来自源头的答案。 Anthropic 公司今天发布了一份极为详尽的内部案例研究，为我们提供了一次罕见的“幕后观察”机会，让我们得以一窥其内部团队——从最核心的产品开发、安全工程，到数据科学、乃至法务和营销团队——是如何将 Claude Code 作为其日常工作的核心伙伴。 这份案例研究的意义非凡，因为它不再是关于“AI 能做什么”的畅想，而是关于“AI 正在如何做”的实录。从数据工程师借助截图在几分钟内解决复杂的 Kubernetes 故障，到毫无编程经验的财务团队用自然语言构建起全自动的数据处理流；从新员工入职第一天就能高效导航庞大的单一代码库，到产品设计师直接将视觉稿转化为可交互的前端原型——我们看到的是一种工作范式的彻底变革以及生产力的“爆炸”！ 本文就翻译自Anthropic的这篇博客文章《How Anthropic teams use Claude Code》，希望各位读者都能从中受益。 Anthropic 的内部团队正在通过 Claude Code 改变其工作流程，使开发人员和非技术人员能够处理复杂项目、自动化任务，并弥合之前限制他们生产力的技能差距。 为了了解更多，我们与以下团队进行了交谈： 数据基础设施 产品开发 安全工程 推理 数据科学与可视化 产品工程 增长营销 产品设计 强化学习 (RL) 工程 法务 通过这些访谈，我们深入了解了不同部门如何使用 Claude Code、它对其工作的影响，以及为其他考虑采用该工具的组织提供的建议。 Claude Code 在数据基础设施领域的应用 数据基础设施团队为全公司的团队组织所有业务数据。他们使用 Claude Code 来自动化常规的数据工程任务、解决复杂的基础设施问题，并为非技术团队成员创建文档化的工作流程，以便他们能够独立地访问和操作数据。 主要 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/how-anthropic-teams-use-claude-code-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/07/25/how-anthropic-teams-use-claude-code">本文永久链接</a> &#8211; https://tonybai.com/2025/07/25/how-anthropic-teams-use-claude-code</p>
<p>当 AI 编程助手从简单的代码补全工具，演变为深度集成于开发者工作流核心的“终端原生 AI”（Terminal-native AI）时，一个根本性的问题浮现出来：<strong>顶尖团队究竟是如何在日常工作中驾驭这股新力量的？</strong> 理论和演示层出不穷，但真实、大规模、跨职能的实践案例却凤毛麟角。</p>
<p>现在，我们得到了来自源头的答案。</p>
<p>Anthropic 公司今天发布了一份极为详尽的内部案例研究，为我们提供了一次罕见的“幕后观察”机会，让我们得以一窥其内部团队——从最核心的产品开发、安全工程，到数据科学、乃至法务和营销团队——是如何将 <strong>Claude Code</strong> 作为其日常工作的核心伙伴。</p>
<p>这份案例研究的意义非凡，因为它不再是关于“AI 能做什么”的畅想，而是关于“AI 正在如何做”的实录。从数据工程师借助截图在几分钟内解决复杂的 Kubernetes 故障，到毫无编程经验的财务团队用自然语言构建起全自动的数据处理流；从新员工入职第一天就能高效导航庞大的单一代码库，到产品设计师直接将视觉稿转化为可交互的前端原型——我们看到的是一种工作范式的彻底变革以及生产力的“爆炸”！</p>
<p>本文就翻译自Anthropic的这篇博客文章《<a href="https://www.anthropic.com/news/how-anthropic-teams-use-claude-code">How Anthropic teams use Claude Code</a>》，希望各位读者都能从中受益。</p>
<hr />
<p>Anthropic 的内部团队正在通过 Claude Code 改变其工作流程，使开发人员和非技术人员能够处理复杂项目、自动化任务，并弥合之前限制他们生产力的技能差距。</p>
<p>为了了解更多，我们与以下团队进行了交谈：</p>
<ul>
<li>数据基础设施</li>
<li>产品开发</li>
<li>安全工程</li>
<li>推理</li>
<li>数据科学与可视化</li>
<li>产品工程</li>
<li>增长营销</li>
<li>产品设计</li>
<li>强化学习 (RL) 工程</li>
<li>法务</li>
</ul>
<p>通过这些访谈，我们深入了解了不同部门如何使用 Claude Code、它对其工作的影响，以及为其他考虑采用该工具的组织提供的建议。</p>
<h2>Claude Code 在数据基础设施领域的应用</h2>
<p>数据基础设施团队为全公司的团队组织所有业务数据。他们使用 Claude Code 来自动化常规的数据工程任务、解决复杂的基础设施问题，并为非技术团队成员创建文档化的工作流程，以便他们能够独立地访问和操作数据。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>使用截图进行 Kubernetes 调试</strong></p>
<p>当 Kubernetes 集群出现故障且无法调度新的 pod 时，团队使用 Claude Code 来诊断问题。他们将仪表盘的截图输入到 Claude Code 中，后者引导他们逐个菜单地浏览 Google Cloud 的 UI，直到发现一个指示 pod IP 地址耗尽的警告。随后，Claude Code 提供了创建新 IP 池并将其添加到集群的确切命令，从而无需网络专家的介入。</p>
<p><strong>为财务团队提供纯文本工作流</strong></p>
<p>工程师向财务团队成员展示了如何编写描述其数据工作流的纯文本文件，然后将其加载到 Claude Code 中以实现完全自动化的执行。没有编程经验的员工可以描述诸如“查询此仪表盘，获取信息，运行这些查询，生成 Excel 输出”之类的步骤，Claude Code 将执行整个工作流，包括询问像日期这样的必需输入。</p>
<p><strong>为新员工提供代码库导航</strong></p>
<p>当新的数据科学家加入团队时，他们被引导使用 Claude Code 来导航庞大的代码库。Claude Code 会读取他们的 Claude.md 文件，为特定任务识别相关文件，解释数据管道的依赖关系，并帮助新员工理解哪些上游数据源为仪表盘提供数据。这取代了传统的数据目录和可发现性工具。</p>
<p><strong>会话结束时的文档更新</strong></p>
<p>团队会要求 Claude Code 总结已完成的工作会话，并在每个任务结束时提出改进建议。这就创建了一个持续改进的循环，其中 Claude Code 帮助优化 Claude.md 文件。</p>
<p><strong>跨多个实例的并行任务管理</strong></p>
<p>在处理长时间运行的数据任务时，团队会在不同的代码仓库中为不同的项目打开多个 Claude Code 实例。每个实例都保持完整的上下文，因此当他们在数小时或数天后切换回来时，Claude Code 能准确记住他们当时正在做什么以及进行到哪里，从而实现了真正的并行工作流管理而不会丢失上下文。</p>
<h3>团队影响</h3>
<p><strong>无需专业知识即可解决基础设施问题</strong></p>
<p>解决了通常需要系统或网络团队成员介入的 Kubernetes 集群问题，使用 Claude Code 诊断问题并提供精确的修复方案。</p>
<p><strong>加速入职流程</strong></p>
<p>新的数据分析师和团队成员可以迅速理解复杂的系统，并在没有大量指导的情况下做出有意义的贡献。</p>
<p><strong>增强的支持工作流</strong></p>
<p>Claude Code 可以处理更大量的数据并识别异常（例如监控 200 个仪表盘），这是人类手动审查无法做到的。</p>
<p><strong>实现了跨团队自助服务</strong></p>
<p>没有编程经验的财务团队现在可以独立执行复杂的数据工作流。</p>
<h3>来自数据基础设施团队的顶级建议</h3>
<p><strong>编写详细的 Claude.md 文件</strong></p>
<p>团队表示，你在 Claude.md 文件中记录工作流、工具和期望越详尽，Claude Code 的表现就越好。这使得 Claude Code 在处理诸如根据现有设计模式建立新数据管道之类的常规任务时表现出色。</p>
<p><strong>对敏感数据使用 MCP 服务器而非 CLI</strong></p>
<p>他们建议使用 MCP 服务器而不是 BigQuery CLI，以便更好地控制 Claude Code 的访问权限，尤其是在处理需要日志记录或有潜在隐私问题的敏感数据时。</p>
<p><strong>分享使用会话</strong></p>
<p>团队举办了分享会，成员们在会上演示了各自的 Claude Code 工作流程。这有助于传播最佳实践，并展示了他们可能未曾发现的各种工具使用方法。</p>
<h2>Claude Code 在产品开发领域的应用</h2>
<p>Claude Code 产品开发团队使用他们自己的产品来为 Claude Code 构建更新，扩展产品的企业级功能和智能体体循环（agentic loop）功能。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>使用自动接受模式进行快速原型设计</strong></p>
<p>工程师通过启用“自动接受模式”（shift+tab）来进行快速原型设计，并建立自主循环，让 Claude 编写代码、运行测试并持续迭代。他们给 Claude 提出他们不熟悉的抽象问题，让它自主工作，然后在最终完善前审查那 80% 完成度的解决方案。团队建议从一个干净的 git 状态开始，并定期提交检查点，以便在 Claude 偏离轨道时可以轻松地恢复任何不正确的更改。</p>
<p><strong>核心功能的同步编码</strong></p>
<p>对于触及应用核心业务逻辑的更关键的功能，团队与 Claude Code 同步工作，提供带有具体实现指令的详细提示。他们在实时监控整个过程，以确保代码质量、风格指南合规性和正确的架构，同时让 Claude 处理重复性的编码工作。</p>
<p><strong>构建 Vim 模式</strong></p>
<p>他们最成功的异步项目之一是为 Claude Code 实现 Vim 键位绑定。他们要求 Claude 构建整个功能，最终实现的约 70% 来自 Claude 的自主工作，只需几次迭代即可完成。</p>
<p><strong>测试生成与错误修复</strong></p>
<p>团队在实现功能后，使用 Claude Code 编写全面的测试，并处理在代码审查中发现的简单错误修复。他们还使用 GitHub Actions 让 Claude 自动处理 Pull Request 中的评论，如格式化问题或函数重命名。</p>
<p><strong>代码库探索</strong></p>
<p>在处理不熟悉的代码库（如单一代码库或 API 端）时，团队使用 Claude Code 快速理解系统的工作方式。他们不再等待 Slack 上的回复，而是直接向 Claude 询问解释和代码引用，从而在上下文切换中节省了大量时间。</p>
<h3>团队影响</h3>
<p><strong>更快的特性实现</strong></p>
<p>Claude Code 成功地实现了像 Vim 模式这样的复杂功能，其中 70% 的代码由 Claude 自主编写。</p>
<p><strong>提高开发速度</strong></p>
<p>该工具可以快速地为功能制作原型并迭代想法，而不会陷入实现细节的泥潭。</p>
<p><strong>通过自动化测试提升代码质量</strong></p>
<p>Claude 生成全面的测试并处理常规的错误修复，在减少手动工作的同时保持了高标准。</p>
<p><strong>更好的代码库探索</strong></p>
<p>团队成员可以迅速熟悉单一代码库中不熟悉的部分，而无需等待同事的回复。</p>
<h3>来自 Claude Code 团队的顶级建议</h3>
<p><strong>创建自给自足的循环</strong></p>
<p>设置 Claude，让它通过自动运行构建、测试和代码检查来验证自己的工作。这使得 Claude 能够更长时间地自主工作并发现自己的错误，在要求它在编写代码之前生成测试时尤其有效。</p>
<p><strong>培养任务分类的直觉</strong></p>
<p>学会区分适合异步处理的任务（外围功能、原型设计）和需要同步监督的任务（核心业务逻辑、关键修复）。产品边缘的抽象任务可以用“自动接受模式”处理，而核心功能则需要更密切的监督。</p>
<p><strong>形成清晰、详细的提示</strong></p>
<p>当组件具有相似的名称或功能时，在你的请求中要极其具体。你的提示越好、越详细，你就越能相信 Claude 能独立工作，而不会意外地更改代码库的错误部分。</p>
<h2>Claude Code 在安全工程领域的应用</h2>
<p>安全工程团队专注于保障软件开发生命周期、供应链安全和开发环境安全。他们广泛使用 Claude Code 进行代码编写和调试。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>复杂的基础设施调试</strong></p>
<p>在处理事故时，他们向 Claude Code 提供堆栈跟踪和文档，要求它在代码库中追踪控制流。这大大缩短了生产问题的解决时间，使他们能够在大约 5 分钟内理解通常需要 10-15 分钟手动代码扫描才能发现的问题。</p>
<p><strong>Terraform 代码审查与分析</strong></p>
<p>对于需要安全审批的基础设施变更，团队将 Terraform 计划复制到 Claude Code 中，并提问“这会做什么？我会后悔吗？”。这创建了更紧密的反馈循环，使安全团队能更快地审查和批准基础设施变更，减少了开发过程中的瓶颈。</p>
<p><strong>文档合成与操作手册（runbooks）</strong></p>
<p>Claude Code 能消化多个文档源，并创建 Markdown 格式的操作手册、故障排除指南和概述。团队使用这些浓缩的文档作为调试实际问题的上下文，创建了比搜索完整知识库更高效的工作流程。</p>
<p><strong>测试驱动的开发工作流</strong></p>
<p>他们不再遵循以前“设计文档 → 粗糙代码 → 重构 → 放弃测试”的模式，而是要求 Claude Code 提供伪代码，引导它完成测试驱动的开发，并在其卡住时定期介入以引导方向，从而产生更可靠和可测试的代码。</p>
<p><strong>上下文切换与项目入职</strong></p>
<p>在为像“dependant”（一个用于安全审批工作流的 Web 应用）这样的现有项目贡献代码时，他们使用 Claude Code 编写、审查和执行用 Markdown 编写并存储在代码库中的规范，使得在几天内（而非几周）就能做出有意义的贡献。</p>
<h3>团队影响</h3>
<p><strong>缩短事故解决时间</strong></p>
<p>通常需要 10-15 分钟手动代码扫描的基础设施调试，现在大约只需要 5 分钟。</p>
<p><strong>改进的安全审查周期</strong></p>
<p>用于安全审批的 Terraform 代码审查速度更快，消除了开发者在等待安全团队批准时的阻塞。</p>
<p><strong>增强的跨职能贡献</strong></p>
<p>团队成员可以在几天内为项目做出有意义的贡献，而无需数周的上下文构建。</p>
<p><strong>更好的文档工作流</strong></p>
<p>从多个来源合成的故障排除指南和操作手册，创建了更高效的调试流程。</p>
<h3>来自安全工程团队的顶级建议</h3>
<p><strong>广泛使用自定义斜杠命令</strong></p>
<p>安全工程团队使用了整个单一代码库中 50% 的自定义斜杠命令实现。这些自定义命令简化了特定的工作流程并加速了重复性任务。</p>
<p><strong>让 Claude 先说</strong></p>
<p>他们不再是提出针对性问题以生成代码片段，而是告诉 Claude Code “边做边提交你的工作”，让它在定期检查的情况下自主工作，从而得到更全面的解决方案。</p>
<p><strong>充分利用其文档能力</strong></p>
<p>除了编码，Claude Code 在合成文档和创建结构化输出方面表现出色。团队提供写作样本和格式偏好，以获得可以立即在 Slack、Google Docs 和其他工具中使用的文档，从而避免界面切换的疲劳。</p>
<h2>Claude Code 在推理领域的应用</h2>
<p>推理团队管理着在 Claude 读取你的提示并生成响应时存储信息的内存系统。团队成员，尤其是那些刚接触机器学习的人，可以广泛使用 Claude Code 来弥补知识差距并加速他们的工作。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>代码库理解与入职</strong></p>
<p>团队严重依赖 Claude Code 在加入复杂代码库时快速理解其架构。他们不再手动搜索 GitHub 仓库，而是要求 Claude 找到调用特定功能的文件，在几秒钟内得到结果，而不是询问同事或手动搜索。</p>
<p><strong>带边缘案例覆盖的单元测试生成</strong></p>
<p>在编写完核心功能后，他们会要求 Claude 编写全面的单元测试。Claude 会自动包含被忽略的边缘案例，在几分钟内完成通常需要大量时间和脑力的工作，就像一个他们可以审查的编码助手。</p>
<p><strong>机器学习概念解释</strong></p>
<p>没有机器学习背景的团队成员依赖 Claude 来解释特定模型的功能和设置。以前需要一个小时谷歌搜索和阅读文档的事情，现在只需要 10-20 分钟，研究时间减少了 80%。</p>
<p><strong>跨语言代码翻译</strong></p>
<p>在测试不同编程语言的功能时，团队会解释他们想要测试的内容，然后 Claude 会用所需的语言（如 Rust）编写逻辑，从而无需为了测试目的而学习新语言。</p>
<p><strong>命令记忆与 Kubernetes 管理</strong></p>
<p>他们不再需要记住复杂的 Kubernetes 命令，而是向 Claude 询问正确的语法，比如“如何获取所有 pod 或部署的状态”，并获得他们基础设施工作所需的确切命令。</p>
<h3>团队影响</h3>
<p><strong>加速机器学习概念学习</strong></p>
<p>通过 Claude Code，他们的研究时间减少了 80%，以前需要一个小时谷歌搜索的事情现在只需要 10-20 分钟。</p>
<p><strong>更快的代码库导航</strong></p>
<p>该工具可以帮助团队成员在几秒钟内找到相关文件并理解系统架构，而不用依赖同事分享知识，后者通常需要几天时间。</p>
<p><strong>全面的测试覆盖</strong></p>
<p>Claude 自动生成带有边缘案例的单元测试，在保持代码质量的同时减轻了脑力负担。</p>
<p><strong>消除语言障碍</strong></p>
<p>团队可以在不熟悉的情况下，在像 Rust 这样的语言中实现功能，而无需学习它。</p>
<h3>来自推理团队的顶级建议</h3>
<p><strong>首先测试知识库功能</strong></p>
<p>尝试问各种问题，看看 Claude 的回答是否比谷歌搜索更快。如果它更快、更准确，那么它就是你工作流程中一个宝贵的时间节省工具。</p>
<p><strong>从代码生成开始</strong></p>
<p>给 Claude 具体指令，要求它编写逻辑，然后验证其正确性。这有助于在将其用于更复杂的任务之前，建立对该工具能力的信任。</p>
<p><strong>用它来编写测试</strong></p>
<p>让 Claude 编写单元测试可以显著减轻日常开发工作的压力。利用这个功能来保持代码质量，而无需花费时间手动思考所有测试用例。</p>
<h2>Claude Code 在数据科学与机器学习工程领域的应用</h2>
<p>数据科学和机器学习工程团队需要复杂的可视化工具来理解模型性能，但构建这些工具通常需要不熟悉的语言和框架的专业知识。Claude Code 使这些团队能够构建生产质量的分析仪表盘，而无需成为全栈开发人员。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>构建 JavaScript/TypeScript 仪表盘应用</strong></p>
<p>尽管对“JavaScript 和 TypeScript 知之甚少”，该团队仍使用 Claude Code 构建了完整的 React 应用，用于可视化强化学习 (RL) 模型的性能和训练数据。他们让 Claude 控制从零开始编写完整的应用程序，比如一个 5000 行的 TypeScript 应用，而无需自己理解代码。这至关重要，因为可视化应用上下文相对较低，不需要理解整个单一代码库，从而允许快速原型设计工具来理解模型在训练和评估期间的性能。</p>
<p><strong>处理重复的重构任务</strong></p>
<p>当面临合并冲突或半复杂的文件重构时——这些任务对于编辑器宏来说过于复杂，但又不足以进行大规模开发——他们会像使用“老虎机”一样使用 Claude Code：提交他们的状态，让 Claude 自主工作 30 分钟，然后要么接受解决方案，要么在不成功时重新开始。</p>
<p><strong>创建持久的分析工具而非一次性笔记本</strong></p>
<p>团队现在让 Claude 构建可以跨未来模型评估重用的永久性 React 仪表盘，而不是构建用完即弃的一次性 Jupyter 笔记本。这很重要，因为理解 Claude 的性能是“团队最重要的事情之一”——他们需要了解模型在训练和评估期间的表现，而“这实际上非同小可，简单的工具无法从一个上升的数字中获得太多信号。”</p>
<p><strong>零依赖任务委托</strong></p>
<p>对于完全不熟悉的代码库或语言中的任务，他们将整个实现委托给 Claude Code，利用其从单一代码库中收集上下文并执行任务的能力，而无需他们实际参与编码过程。这使得他们能够在专业领域之外提高生产力，而不是花时间学习新技术。</p>
<h3>团队影响</h3>
<p><strong>实现 2-4 倍的时间节省</strong></p>
<p>过去繁琐但可手动管理的常规重构任务现在完成得更快了。</p>
<p><strong>在不熟悉的语言中构建复杂的应用程序</strong></p>
<p>尽管 JavaScript/TypeScript 经验最少，也创建了 5000 行的 TypeScript 应用。</p>
<p><strong>从一次性工具转向持久性工具</strong></p>
<p>不再使用一次性的 Jupyter 笔记本，现在构建可重用的 React 仪表盘进行模型分析。</p>
<p><strong>直接的模型改进洞察</strong></p>
<p>第一手的 Claude Code 经验为未来模型迭代中更好的内存系统和用户体验改进提供了信息。</p>
<p><strong>实现了可视化驱动的决策</strong></p>
<p>通过先进的可视化工具，更好地理解 Claude 在训练和评估期间的性能。</p>
<h3>来自数据科学与机器学习工程团队的建议</h3>
<p><strong>像玩老虎机一样对待它</strong></p>
<p>在让 Claude 工作之前保存你的状态，让它运行 30 分钟，然后要么接受结果，要么重新开始，而不是试图纠正错误。从头开始通常比试图修复 Claude 的错误有更高的成功率。</p>
<p><strong>在需要时为了简单而中断</strong></p>
<p>在监督时，不要犹豫，停下来问 Claude “你为什么这么做？试试更简单的方法。” 模型默认倾向于更复杂的解决方案，但对更简单方法的请求反应良好。</p>
<h2>Claude Code 在产品工程领域的应用</h2>
<p>产品工程团队致力于 PDF 支持、引用和网络搜索等功能，这些功能为 Claude 的上下文窗口带来了额外的知识。跨越大型、复杂的代码库工作意味着不断遇到不熟悉的代码部分，需要花费大量时间来理解要检查哪些文件，并在进行更改前建立上下文。Claude Code 改善了这种体验，它作为一个向导，可以帮助他们理解系统架构、识别相关文件并解释复杂的交互。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>第一步工作流规划</strong></p>
<p>团队将 Claude Code 作为任何任务的“第一站”，要求它确定要检查哪些文件以进行错误修复、功能开发或分析。这取代了在开始工作前手动导航代码库和收集上下文的传统耗时过程。</p>
<p><strong>跨代码库的独立调试</strong></p>
<p>团队现在有信心在不向他人求助的情况下，处理代码库中不熟悉部分的错误。他们可以问 Claude “你认为你能修复这个 bug 吗？这是我看到的行为”，并且通常能立即取得进展，这在以前由于所需的时间投入而不可行。</p>
<p><strong>通过内部测试进行模型迭代测试</strong></p>
<p>Claude Code 自动使用最新的研究模型快照，使其成为体验模型变化的主要方式。这为团队在开发周期中提供了关于模型行为变化的直接反馈，这是他们以前在发布时没有经历过的。</p>
<p><strong>消除上下文切换的开销</strong></p>
<p>他们不再需要将代码片段复制和拖动到 Claude.ai 中，同时还要详细解释问题，而是可以直接在 Claude Code 中提问，无需额外的上下文收集，大大减少了脑力开销。</p>
<h3>团队影响</h3>
<p><strong>增强了处理不熟悉领域的信心</strong></p>
<p>团队成员可以独立地在不熟悉的代码库中调试错误和调查事件。</p>
<p><strong>在上下文收集中节省了大量时间</strong></p>
<p>Claude Code 消除了将代码片段复制和拖动到 Claude.ai 的开销，减少了上下文切换的负担。</p>
<p><strong>更快的轮岗入职</strong></p>
<p>轮岗到新团队的工程师可以迅速导航不熟悉的代码库，并在没有大量同事咨询的情况下做出有意义的贡献。</p>
<p><strong>提升了开发者的幸福感</strong></p>
<p>团队报告说，在日常工作流程中减少了摩擦，感觉更快乐、更有效率。</p>
<h3>来自产品工程团队的顶级建议</h3>
<p><strong>将其视为迭代的伙伴，而非一次性的解决方案</strong></p>
<p>不要期望 Claude 能立即解决问题，而是把它当作一个你与之迭代的合作者。这比试图在第一次尝试中就获得完美的解决方案效果更好。</p>
<p><strong>用它来建立在不熟悉领域的信心</strong></p>
<p>不要犹豫，去处理你专业领域之外的错误或调查事件。Claude Code 使得在通常需要大量上下文构建的领域独立工作成为可能。</p>
<p><strong>从最少的信息开始</strong></p>
<p>从你需要的最基本信息开始，让 Claude 引导你完成整个过程，而不是预先加载大量的解释。</p>
<h2>Claude Code 在增长营销领域的应用</h2>
<p>增长营销团队专注于在付费搜索、付费社交、移动应用商店、电子邮件营销和 SEO 方面建立效果营销渠道。作为一个非技术背景的单人团队，他们使用 Claude Code 来自动化重复性的营销任务，并创建传统上需要大量工程资源的智能体工作流。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>自动化 Google Ads 广告创意生成</strong></p>
<p>团队构建了一个智能体工作流，该工作流处理包含数百个现有广告及其效果指标的 CSV 文件，识别表现不佳的广告进行迭代，并生成符合严格字符限制（标题 30 个字符，描述 90 个字符）的新变体。使用两个专门的子智能体（一个用于标题，一个用于描述），该系统可以在几分钟内生成数百个新广告，而无需跨多个活动进行手动创建。这使他们能够大规模地进行测试和迭代，这是以前需要大量时间才能实现的。</p>
<p><strong>用于大规模创意制作的 Figma 插件</strong></p>
<p>他们开发了一个 Figma 插件，而不是为付费社交广告手动复制和编辑静态图像。该插件能识别框架并以编程方式通过替换标题和描述生成多达 100 个广告变体，将过去需要数小时的复制粘贴工作减少到每批次半秒。这使得创意产出提高了 10 倍，让团队可以在关键社交渠道上测试更多样化的创意变体。</p>
<p><strong>用于活动分析的 Meta Ads MCP 服务器</strong></p>
<p>他们创建了一个与 Meta Ads API 集成的 MCP 服务器，以直接在 Claude 桌面应用内查询活动表现、支出数据和广告效果，从而无需在不同平台之间切换进行性能分析，节省了关键时间，而每一个效率的提升都转化为更高的投资回报率（ROI）。</p>
<p><strong>带记忆系统的高级提示工程</strong></p>
<p>他们实现了一个基本的记忆系统，记录跨广告迭代的假设和实验，使系统在生成新变体时能够提取以前的测试结果作为上下文，从而创建了一个自我改进的测试框架。这使得系统性的实验成为可能，而这在以前是无法手动追踪的。</p>
<h3>团队影响</h3>
<p><strong>在重复性任务上节省了大量时间</strong></p>
<p>Claude Code 将广告文案创作时间从 2 小时减少到 15 分钟，为团队腾出更多时间进行战略性工作。</p>
<p><strong>创意产出增加 10 倍</strong></p>
<p>通过自动化广告生成和 Figma 集成，团队现在可以在各个渠道测试更多的广告变体，以获取最新的视觉设计元素。</p>
<p><strong>像一个更大的团队一样运作</strong></p>
<p>团队可以处理传统上需要专门工程资源的大型开发任务。</p>
<p><strong>战略焦点的转移</strong></p>
<p>团队可以花更多时间在整体战略和构建智能体自动化上，而不是手动执行。</p>
<h3>来自增长营销团队的顶级建议</h3>
<p><strong>识别支持 API 的重复性任务</strong></p>
<p>寻找涉及使用带有 API 的工具（如广告平台、设计工具、分析平台）进行重复性操作的工作流。这些是自动化的主要候选者，也是 Claude Code 提供最大价值的地方。</p>
<p><strong>将复杂工作流分解为专门的子智能体</strong></p>
<p>不要试图在一个提示或工作流中处理所有事情，而是为特定任务创建单独的智能体（例如标题智能体 vs. 描述智能体）。这在处理复杂需求时使调试更容易，并提高了输出质量。</p>
<p><strong>在编码前进行彻底的头脑风暴和提示规划</strong></p>
<p>花大量时间预先使用 Claude.ai 来思考你的整个工作流，然后让 Claude.ai 为 Claude Code 创建一个全面的提示和代码结构以供参考。此外，要循序渐进地工作，而不是要求一次性的解决方案，以避免 Claude 被复杂的任务压垮。</p>
<h2>Claude Code 在产品设计领域的应用</h2>
<p>产品设计团队支持 Claude Code、Claude.ai 和 Anthropic API，专注于构建 AI 产品。即使是非开发人员也可以使用 Claude Code 来弥合设计和工程之间的传统鸿沟，使他们能够直接实现其设计愿景，而无需与工程师进行大量的来回迭代。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>前端润色和状态管理变更</strong></p>
<p>团队不再创建详尽的设计文档，并与工程师就视觉调整（字体、颜色、间距）进行多轮反馈，而是直接使用 Claude Code 实现这些更改。工程师们注意到，他们正在进行“通常不会看到设计师做出的大的状态管理更改”，这使他们能够达到他们所设想的确切质量。</p>
<p><strong>GitHub Actions 自动化工单处理</strong></p>
<p>利用 Claude Code 的 GitHub 集成，他们只需提交描述所需更改的问题/工单，Claude 就会自动提出代码解决方案，而无需打开 Claude Code，为他们持续积压的润色任务创建了一个无缝的错误修复和功能优化工作流。</p>
<p><strong>快速交互式原型制作</strong></p>
<p>通过将模型图像粘贴到 Claude Code 中，他们可以生成功能齐全的原型，工程师可以立即理解并在此基础上进行迭代，取代了传统的静态 Figma 设计周期，后者需要大量的解释和到工作代码的转换。</p>
<p><strong>边缘案例发现和系统架构理解</strong></p>
<p>团队使用 Claude Code 来绘制错误状态、逻辑流和不同的系统状态，使他们能够在设计阶段识别边缘案例，而不是在开发后期才发现，从而从根本上提高了他们初始设计的质量。</p>
<p><strong>复杂的文案更改和法律合规</strong></p>
<p>对于像在整个代码库中移除“研究预览”消息这样的任务，他们使用 Claude Code 查找所有实例，审查周围的文案，与法务部门实时协调更改，并实施更新，这个过程只需要两个 30 分钟的电话会议，而不是一周的来回协调。</p>
<h3>团队影响</h3>
<p><strong>转变了核心工作流</strong></p>
<p>Claude Code 成为主要的设计工具，Figma 和 Claude Code 的使用时间占到了 80%。</p>
<p><strong>2-3 倍的执行速度</strong></p>
<p>以前需要与工程师大量来回沟通的视觉和状态管理更改现在可以直接实现。</p>
<p><strong>周期时间从数周缩短到数小时</strong></p>
<p>像发布 Google Analytics 消息这样需要一周协调的复杂项目，现在可以在两个 30 分钟的电话会议中完成。</p>
<p><strong>两种截然不同的用户体验</strong></p>
<p>开发者获得了一种“增强的工作流”（更快的执行），而非技术用户则获得了“天哪，我现在也能像开发者一样工作了！”的工作流。</p>
<p><strong>改善了设计与工程的协作</strong></p>
<p>Claude Code 改善了沟通和问题解决速度，因为设计师在不必与工程师紧密合作的情况下，就能理解系统的约束和可能性。</p>
<h3>来自产品设计团队的顶级建议</h3>
<p><strong>从工程师那里获得正确的设置帮助</strong></p>
<p>让工程团队的同事帮助进行初始的代码仓库设置和权限配置——对于非开发人员来说，技术入职具有挑战性，但一旦配置完成，它将为日常工作流带来变革。</p>
<p><strong>使用自定义记忆文件来引导 Claude 的行为</strong></p>
<p>创建具体的指令，告诉 Claude 你是一个编码经验很少的设计师，需要详细的解释和更小、增量的更改，这会显著提高 Claude 响应的质量，并使其不那么令人生畏。</p>
<p><strong>利用图像粘贴进行原型制作</strong></p>
<p>使用 Command+V 将截图直接粘贴到 Claude Code 中。它在读取设计和生成功能代码方面表现出色，对于将静态模型转化为工程师可以立即理解和构建的交互式原型非常有价值。</p>
<h2>Claude Code 在 RL 工程领域的应用</h2>
<p>RL 工程团队专注于 RL 中的高效采样和跨集群的权重传输。他们主要使用 Claude Code 编写中小型功能、进行调试，以及理解复杂的代码库，采用一种包含频繁检查点和回滚的迭代方法。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>有监督的自主功能开发</strong></p>
<p>团队让 Claude Code 编写大部分中小型功能的代码，同时提供监督，例如为权重传输组件实现认证机制。他们以交互方式工作，允许 Claude 主导，但在其偏离轨道时进行引导。</p>
<p><strong>测试生成与代码审查</strong></p>
<p>在自己实现更改后，团队会要求 Claude Code 添加测试或审查他们的代码。这种自动化的测试工作流在常规但重要的质量保证任务上节省了大量时间。</p>
<p><strong>调试和错误调查</strong></p>
<p>他们使用 Claude Code 调试错误，结果好坏参半。有时它能立即识别问题并添加相关测试，而其他时候它难以理解问题，但总的来说，在它起作用时提供了价值。</p>
<p><strong>代码库理解和调用栈分析</strong></p>
<p>他们工作流程中最大的变化之一是使用 Claude Code 快速获取相关组件和调用栈的摘要，取代了手动阅读代码或生成大量调试输出。</p>
<p><strong>Kubernetes 操作指导</strong></p>
<p>他们经常向 Claude 询问 Kubernetes 操作，这些操作通常需要大量的谷歌搜索或询问基础设施工程的同事，从而获得配置和部署问题的即时答案。</p>
<h3>开发工作流影响</h3>
<p><strong>启用了实验性方法</strong></p>
<p>他们现在使用一种“尝试并回滚”的方法，频繁提交检查点，以便测试 Claude 的自主实现尝试，并在需要时恢复，从而实现更具实验性的开发。</p>
<p><strong>加速了文档工作</strong></p>
<p>Claude Code 自动添加有用的注释，节省了大量的文档时间，尽管他们注意到它有时会在奇怪的地方添加注释或使用有问题的代码组织方式。</p>
<p><strong>有局限性的提速</strong></p>
<p>虽然 Claude Code 可以在“相对较少的时间”内实现中小型 PR，但他们承认，它只有大约三分之一的时间能在第一次尝试时成功，需要额外的指导或手动干预。</p>
<h3>来自 RL 工程团队的顶级建议</h3>
<p><strong>为特定模式定制你的 Claude.md 文件</strong></p>
<p>在你的 Claude.md 文件中添加指令，以防止 Claude 犯重复的工具调用错误，比如告诉它“运行 pytest 而不是 run，不要不必要地 cd &#8211; 只需使用正确的路径。” 这显著提高了一致性。</p>
<p><strong>使用检查点密集的工作流</strong></p>
<p>在 Claude 进行更改时定期提交你的工作，以便在实验不成功时轻松回滚。这使得开发能够采用更具实验性的方法，而没有风险。</p>
<p><strong>先尝试一次性完成，然后协作</strong></p>
<p>给 Claude 一个快速的提示，让它尝试完成整个实现。如果成功了（大约三分之一的时间），你就节省了大量时间。如果没有，那就切换到更具协作性的、引导式的方法。</p>
<h2>Claude Code 在法务领域的应用</h2>
<p>法务团队通过实验和了解 Anthropic 产品供应的愿望，发现了 Claude Code 的潜力。此外，一名团队成员有一个个人用例，涉及为家庭和工作创建可访问性工具原型，展示了该技术为非开发人员提供的力量。</p>
<h3>主要 Claude Code 用例</h3>
<p><strong>为家庭成员定制的可访问性解决方案</strong></p>
<p>团队成员为有医疗诊断导致说话困难的家庭成员构建了沟通助手。在短短一个小时内，一个人使用原生的语音到文本功能创建了一个预测性文本应用，该应用能建议回复并使用语音库说出它们，解决了语言治疗师推荐的现有可访问性工具中的空白。</p>
<p><strong>法务部门工作流自动化</strong></p>
<p>团队创建了原型“电话树”系统，以帮助团队成员在 Anthropic 与合适的律师联系，展示了法务部门如何在没有传统开发资源的情况下为常见任务构建自定义工具。</p>
<p><strong>团队协调工具</strong></p>
<p>经理们构建了 G Suite 应用，可以自动化每周的团队更新，并跨产品跟踪法律审查状态，使律师能够通过简单的按钮点击而不是电子表格管理来快速标记需要审查的项目。</p>
<p><strong>用于解决方案验证的快速原型制作</strong></p>
<p>他们使用 Claude Code 快速构建功能原型，可以向领域专家展示（比如向 UCSF 的专家展示可访问性工具），以验证想法并在投入更多时间之前识别现有解决方案。</p>
<h3>工作风格与影响</h3>
<p><strong>在 Claude.ai 中规划，在 Claude Code 中构建</strong></p>
<p>他们使用一个两步流程，首先在 Claude.ai 中进行头脑风暴和规划，然后转移到 Claude Code 进行实现，要求它放慢速度并逐步工作，而不是一次性输出所有内容。</p>
<p><strong>视觉优先的方法</strong></p>
<p>他们经常使用截图向 Claude Code 展示他们想要的界面外观，然后根据视觉反馈进行迭代，而不是用文字描述功能。</p>
<p><strong>原型驱动的创新</strong></p>
<p>他们强调克服分享“傻瓜式”或“玩具式”原型的恐惧，因为这些演示能激励他人看到他们以前没有想到的可能性。</p>
<h3>安全与合规意识</h3>
<p><strong>MCP 集成问题</strong></p>
<p>产品律师使用 Claude Code 立即识别深度 MCP 集成的安全影响，指出随着 AI 工具访问更敏感的系统，保守的安全态势将构成障碍。</p>
<p><strong>合规工具的优先级</strong></p>
<p>他们倡导随着 AI 能力的扩展迅速构建合规工具，认识到创新与风险管理之间的平衡。</p>
<h3>来自法务部门的顶级建议</h3>
<p><strong>首先在 Claude.ai 中进行详尽规划</strong></p>
<p>在转向 Claude Code 之前，使用 Claude 的对话界面充实你的整个想法。然后要求 Claude 将所有内容总结成一个分步的实现提示。</p>
<p><strong>增量和可视化地工作</strong></p>
<p>要求 Claude 放慢速度，一次实现一个步骤，这样你就可以复制粘贴而不会被淹没。大量使用截图来展示你想要的界面外观。</p>
<p><strong>尽管不完美也要分享原型</strong></p>
<p>克服隐藏“玩具”项目或未完成工作的冲动。分享原型有助于他人看到可能性，并激发通常不互动的部门之间的创新。</p>
<p><strong><a href="https://www.anthropic.com/claude-code">立即开始使用 Claude Code</a>吧。</strong></p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/gemini-cli-starting-guide-qr.png" alt="" /></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/07/25/how-anthropic-teams-use-claude-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>你的命令行，即将迎来一场“AI 革命”</title>
		<link>https://tonybai.com/2025/07/09/gemini-cli-starting-guide/</link>
		<comments>https://tonybai.com/2025/07/09/gemini-cli-starting-guide/#comments</comments>
		<pubDate>Wed, 09 Jul 2025 00:23:57 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[ChatGPT]]></category>
		<category><![CDATA[ClaudeCode]]></category>
		<category><![CDATA[Codex]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[Emacs]]></category>
		<category><![CDATA[gemini-cli]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[JetBrains]]></category>
		<category><![CDATA[MCP]]></category>
		<category><![CDATA[openai]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vscode]]></category>
		<category><![CDATA[代理]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[智能体]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4887</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/07/09/gemini-cli-starting-guide 大家好，我是Tony Bai。 在软件开发的历史长河中，我们与机器的交互界面经历了一场有趣的轮回。 曾几何时，发光的绿色字符在黑色屏幕上跳动，命令行是我们掌控一切的神圣权杖。从编辑器（Vim/Emacs）到编译器，再到版本控制，整个世界都安然地存在于终端的心跳之中。 随后，图形用户界面（GUI）带来了集成开发环境（IDE）的黄金时代。Borland、Visual Studio、Eclipse、JetBrains&#8230; 我们将一切都“集成”到了一个窗口里，享受着点击、拖拽和可视化调试带来的便利。命令行似乎一度退居次席，成了执行零散脚本的“后台工具”。 而今天，当我们以为 VS Code 这样轻快、插件丰富的编辑器已经统一江湖时，一股强劲的“复古之风”正悄然刮起。但这一次，它并非简单的怀旧，而是一场由 AI 驱动的、向命令行的“伟大回归”。 为什么是现在？ 因为 AI 的出现，再次打破了 IDE 创造的“完美闭环”。我们发现自己又一次陷入了新的“工作流摩擦”：我们的代码在一个窗口，而我们的 AI “外脑”（ChatGPT/Gemini Web）在另一个窗口。我们成了上下文的搬运工，在复制粘贴中消耗着宝贵的专注力。 IDE 插件虽有所缓解，但它们更像是被“关在笼子里”的 AI，能力受限于 IDE 提供的 API。它们无法真正理解你的整个系统环境，无法为你执行一条 docker build 命令，更无法调用你私有的测试脚本。 我们需要的，不仅仅是一个会写代码的 AI。我们需要一个能理解我们整个工作流，并能动手执行的 AI。敏锐的开发者和 AI 公司都已意识到，下一个效率的爆发点，不在 GUI，而在那片最经典、最高效的战场——命令行。 这，正是这场“命令行革命”的核心。 于是，一个全新的物种 “命令行AI智能体 (Command-Line AI Agent)” 开始涌现。OpenAI Codex、Claude Code等拥有强大能力的商业公司背书的各类智能体脚本便像雨后春笋般出现。而在这一新兴的赛道上，Google也携其 Gemini CLI，给出了一个与众不同的答案。它更侧重于工作流自动化 (Workflow Automation)。更具吸引力的是，通过个人 Google 账户认证，你就能享受到慷慨的免费使用额度，这极大地降低了每一位开发者体验这场命令行革命的门槛。 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/gemini-cli-starting-guide-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/07/09/gemini-cli-starting-guide">本文永久链接</a> &#8211; https://tonybai.com/2025/07/09/gemini-cli-starting-guide</p>
<p>大家好，我是Tony Bai。</p>
<p>在软件开发的历史长河中，我们与机器的交互界面经历了一场有趣的轮回。</p>
<p>曾几何时，发光的绿色字符在黑色屏幕上跳动，命令行是我们掌控一切的神圣权杖。从编辑器（Vim/Emacs）到编译器，再到版本控制，整个世界都安然地存在于终端的心跳之中。</p>
<p>随后，图形用户界面（GUI）带来了集成开发环境（IDE）的黄金时代。Borland、Visual Studio、Eclipse、JetBrains&#8230; 我们将一切都“集成”到了一个窗口里，享受着点击、拖拽和可视化调试带来的便利。命令行似乎一度退居次席，成了执行零散脚本的“后台工具”。</p>
<p>而今天，当我们以为 VS Code 这样轻快、插件丰富的编辑器已经统一江湖时，一股强劲的“复古之风”正悄然刮起。但这一次，它并非简单的怀旧，而是一场由 <strong>AI 驱动的、向命令行的“伟大回归”</strong>。</p>
<p><strong>为什么是现在？</strong></p>
<p>因为 AI 的出现，再次打破了 IDE 创造的“完美闭环”。我们发现自己又一次陷入了新的“工作流摩擦”：我们的代码在一个窗口，而我们的 AI “外脑”（ChatGPT/Gemini Web）在另一个窗口。我们成了上下文的搬运工，在复制粘贴中消耗着宝贵的专注力。</p>
<p>IDE 插件虽有所缓解，但它们更像是被“关在笼子里”的 AI，能力受限于 IDE 提供的 API。它们无法真正理解你的整个系统环境，无法为你执行一条 docker build 命令，更无法调用你私有的测试脚本。</p>
<p>我们需要的，不仅仅是一个会写代码的 AI。我们需要一个能<strong>理解我们整个工作流</strong>，并能<strong>动手执行</strong>的 AI。敏锐的开发者和 AI 公司都已意识到，下一个效率的爆发点，不在 GUI，而在那片最经典、最高效的战场——命令行。</p>
<p>这，正是这场“命令行革命”的核心。</p>
<p>于是，一个全新的物种 “命令行AI智能体 (Command-Line AI Agent)” 开始涌现。OpenAI Codex、Claude Code等拥有强大能力的商业公司背书的各类智能体脚本便像雨后春笋般出现。而在这一新兴的赛道上，Google也携其 Gemini CLI，给出了一个与众不同的答案。它更侧重于工作流自动化 (Workflow Automation)。更具吸引力的是，通过个人 Google 账户认证，你就能享受到慷慨的免费使用额度，这极大地降低了每一位开发者体验这场命令行革命的门槛。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/gemini-cli-starting-guide-01-3.png" alt="" /></p>
<p>正是因为 Gemini CLI 的这种“慷慨”，我认为它值得一次系统而深入的探索。</p>
<p>我即将开启一个全新的微专栏系列 <strong>《Gemini CLI：重新定义命令行 AI 开发》</strong>，该专栏将用 <strong>5篇由浅入深的实战文章</strong>，向你完整地展示，当今最前沿的大语言模型(比如Gemini 2.5 pro)，是如何与开发世界最经典、最高效的交互界面——命令行——相结合，从而迸发出惊人的能量。此外，专栏中的示例均采用Go代码。</p>
<p>在这个系列中，你将看到：</p>
<ul>
<li>
<p><strong>第一篇《入门篇》：</strong> 我们将为你带来初见的“Wow 时刻”。你将看到 Gemini CLI 如何仅用一个 @ 符号，就读懂并分析一个你完全陌生的 Go 项目，这是一种你从未体验过的、AI 与本地文件系统的深度融合。</p>
</li>
<li>
<p><strong>第二篇《实战篇》：</strong> 我们将带你彻底驾驭 @、!、/ 这三驾马车，在真实的 Go 项目中，完成从代码分析、编译测试到 Git 操作的全流程。我们将让你相信，大部分开发任务，都可以且应该在命令行中一气呵成。</p>
</li>
<li>
<p><strong>第三篇《进阶篇》：</strong> 我们将为你系上 AI 时代的“安全带”。你将掌握 <strong>Checkpointing (快照回滚)</strong> 机制，让你可以像玩游戏读档一样，随时回退 AI 的任何一次代码修改，从而安心地让它进行最大胆的重构实验。</p>
</li>
<li>
<p><strong>第四篇《扩展篇》：</strong> 我们将带你扮演“造物主”的角色。你将学会如何通过<strong>自定义工具</strong>和 <strong>MCP 服务器</strong>，将你自己的脚本、公司的内部 API，甚至任何你能想到的外部系统，全部接入 Gemini CLI 的能力版图，打造真正属于你的神器。</p>
</li>
<li>
<p><strong>第五篇《应用篇》：</strong> 我们将展示一个终极工作流。如何用<strong>一句自然语言指令</strong>，驱动 AI 自动完成<strong>在线研究、信息整合、内容创作，并最终将一篇完整的 Markdown 技术报告保存在你的本地</strong>。这，是自动化思想的极致体现。</p>
</li>
</ul>
<p>这不关乎怀旧，这关乎进化。</p>
<p>这不是退回终端，而是带着 AI 的力量，重返我们最熟悉的战场。</p>
<p>如果你对提升开发效率有极致的追求，如果你相信最好的工具就应该在弹指之间，那么，请锁定我们。</p>
<p><strong>点击下方卡片，即刻关注，与我们一同见证这场正在发生的革命！</strong></p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/gemini-cli-starting-guide-qr.png" alt="" /></p>
<hr />
<p>如果你和我们一样，对探索 Go 与 AI 的前沿交叉领域充满热情，那么这个微专栏仅仅是一个开始。</p>
<p>为了感谢核心读者的支持，并打造一个更具深度和互动性的交流平台，我决定：</p>
<p><strong>本付费微专栏的全部 5 篇文章，将在我的知识星球「Go &amp; AI 精进营」中同步免费发布！</strong></p>
<p><strong>扫描下方二维码，加入「Go &amp; AI 精进营」，与我们一起，站在未来看现在。</strong></p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-and-ai-tribe-zsxq-small-card.jpg" alt="img{512x368}" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/07/09/gemini-cli-starting-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>爽就完了！Go语言的“简单之美”为何让开发者直呼过瘾？</title>
		<link>https://tonybai.com/2025/06/12/grog-brain-heaven/</link>
		<comments>https://tonybai.com/2025/06/12/grog-brain-heaven/#comments</comments>
		<pubDate>Thu, 12 Jun 2025 01:00:22 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[defer]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[gobuild]]></category>
		<category><![CDATA[gofmt]]></category>
		<category><![CDATA[goland]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[gomodule]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[gotest]]></category>
		<category><![CDATA[govet]]></category>
		<category><![CDATA[grop-brain]]></category>
		<category><![CDATA[reddit]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[stdlib]]></category>
		<category><![CDATA[toolchain]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vscode]]></category>
		<category><![CDATA[关键字]]></category>
		<category><![CDATA[复杂性]]></category>
		<category><![CDATA[多返回值]]></category>
		<category><![CDATA[大道至简]]></category>
		<category><![CDATA[工具链]]></category>
		<category><![CDATA[并发]]></category>
		<category><![CDATA[标准库]]></category>
		<category><![CDATA[泛型]]></category>
		<category><![CDATA[短变量声明]]></category>
		<category><![CDATA[继承]]></category>
		<category><![CDATA[编译器]]></category>
		<category><![CDATA[软件工程]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4813</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/06/12/grog-brain-heaven 大家好，我是Tony Bai。 最近，在国外的技术论坛 Reddit 的 Go 语言版块上，一个标题为“Go is so much fun, Grog brain heaven”的帖子，引爆了 Gopher 们的讨论热情。发帖的开发者用一种非常接地气的“原始人 (Grog)”口吻，激情赞扬了 Go 语言，核心就一个字——“爽！” 他列举了一堆理由：关键词少、特殊字符少、概念少、编译器快、工具链好用、标准库给力、没有复杂的构建系统……总而言之，Go 语言对于那些厌倦了复杂性、只想专注于“造东西”的开发者来说，简直就是“天堂”。 这个帖子迅速获得了大量 Go 开发者的强烈共鸣。一位从 Scala 转到 Go 的开发者形容这种体验像是“从100倍重力训练环境出来，到了只有1倍重力的地方，认知负荷大大降低。在Go里你就是直接做事，没有魔法，没有废话，简单直接。” 另一位开发者则惊叹于 Go 工具链的便捷：“只需安装 SDK 就完事了！” 更有甚者直言，Go 的杀手级特性恰恰在于其“缺乏特性 (lack of features)”。 这些发自肺腑的“声音”，不禁让我们深思：在这个技术日新月异、语言特性层出不穷的时代，为什么 Go 语言这种看似“朴素”的“简单”，反而能让如此多的开发者直呼过瘾，成为他们心中“YYDS”？ 在这篇文章中，我们就挑出原贴中几个典型的声音，一起来解读一下。 “Grog脑天堂”的呼唤：返璞归真，大道至简 原帖中提到的“Grog brain heaven”，我们可以理解为一种开发者对纯粹、直接、易于理解和掌控的技术的向往。尤其是在经历了那些充满“魔法”、特性繁杂、需要“JVM柔术”才能驾驭的复杂系统和语言的“洗礼”之后，Go 的出现就像一股清流，让人神清气爽。 “Grog” （可以想象成一个崇尚简单直接的原始人）喜欢造东西，不喜欢猜谜。Go 语言恰好满足了“Grog”的核心诉求： 学得快，忘得慢： 关键词少、特殊字符少、概念少。这意味着学习曲线平缓，上手极快，心智负担极低。你不需要记住成百上千的语法糖或复杂的元编程技巧。 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/grog-brain-heaven-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/06/12/grog-brain-heaven">本文永久链接</a> &#8211; https://tonybai.com/2025/06/12/grog-brain-heaven</p>
<p>大家好，我是Tony Bai。</p>
<p>最近，在国外的技术论坛 Reddit 的 Go 语言版块上，一个标题为“<a href="https://www.reddit.com/r/golang/comments/1l8dxr7/go_is_so_much_fun_grog_brain_heaven/">Go is so much fun, Grog brain heaven</a>”的帖子，引爆了 Gopher 们的讨论热情。发帖的开发者用一种非常接地气的“原始人 (Grog)”口吻，激情赞扬了 Go 语言，核心就一个字——<strong>“爽！”</strong> 他列举了一堆理由：关键词少、特殊字符少、概念少、编译器快、工具链好用、标准库给力、没有复杂的构建系统……总而言之，Go 语言对于那些厌倦了复杂性、只想专注于“造东西”的开发者来说，简直就是“天堂”。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/grog-brain-heaven-2.png" alt="" /></p>
<p>这个帖子迅速获得了大量 Go 开发者的强烈共鸣。一位从 Scala 转到 Go 的开发者形容这种体验像是“从100倍重力训练环境出来，到了只有1倍重力的地方，认知负荷大大降低。在Go里你就是直接做事，没有魔法，没有废话，简单直接。” 另一位开发者则惊叹于 Go 工具链的便捷：“只需安装 SDK 就完事了！” 更有甚者直言，Go 的杀手级特性恰恰在于其“缺乏特性 (lack of features)”。</p>
<p>这些发自肺腑的“声音”，不禁让我们深思：在这个技术日新月异、语言特性层出不穷的时代，<strong>为什么 Go 语言这种看似“朴素”的“简单”，反而能让如此多的开发者直呼过瘾，成为他们心中“YYDS”？</strong> 在这篇文章中，我们就挑出原贴中几个典型的声音，一起来解读一下。</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<h2>“Grog脑天堂”的呼唤：返璞归真，大道至简</h2>
<p>原帖中提到的“Grog brain heaven”，我们可以理解为一种开发者对纯粹、直接、易于理解和掌控的技术的向往。尤其是在经历了那些充满“魔法”、特性繁杂、需要“JVM柔术”才能驾驭的复杂系统和语言的“洗礼”之后，Go 的出现就像一股清流，让人神清气爽。</p>
<p>“Grog” （可以想象成一个崇尚简单直接的原始人）喜欢造东西，不喜欢猜谜。Go 语言恰好满足了“Grog”的核心诉求：</p>
<ul>
<li><strong>学得快，忘得慢：</strong> 关键词少、特殊字符少、概念少。这意味着学习曲线平缓，上手极快，心智负担极低。你不需要记住成百上千的语法糖或复杂的元编程技巧。</li>
<li><strong>写得顺，读得懂：</strong> 直观的类 C 风格编程，对于有其他主流语言背景的开发者来说非常友好。代码通常自上而下、顺序执行，没有复杂的隐式行为或“魔法”般的控制跳转，使得理解和调试代码变得简单直接。</li>
<li><strong>用得爽，不出错：</strong>
<ul>
<li>defer 语句以其简洁实用的方式解决了资源释放等常见问题，写起来顺手，读起来明白。</li>
<li>error 作为普通值返回，让错误处理变得明确和可控，告别了try-catch嵌套和异常满天飞的噩梦。</li>
<li>多返回值和”inline declaration and definition”等特性，进一步提升了编码的流畅性和代码的可读性。</li>
</ul>
</li>
</ul>
<blockquote>
<p>注：发帖者所说的 “inline declaration and definition” 大概率是指向 Go 语言的短变量声明 :=。 这个特性极大地提升了 Go 代码的简洁性和编写效率，减少了冗余的类型声明，让开发者可以更专注于逻辑本身。当然，构体、切片、map的字面量初始化，以及匿名函数的即时定义也都体现了声明、定义、初始化等操作可以“一气呵成”的特点，也符合“inline declaration and definition”的直观感受。</p>
</blockquote>
<h2>“少即是多”：Go 语言设计哲学的胜利</h2>
<p>Go 语言的“简单”并非功能的缺失或设计的草率，而是<strong>一种经过深思熟虑的、以解决实际工程问题为导向的选择</strong>。它是 Go 语言“少即是多”设计哲学的具体体现，是有意为之的克制，是对不必要复杂性的摒弃。</p>
<p>正如一位 Go 开发者在评论中所言：<strong>“它的杀手级特性在于其缺乏特性。”</strong> Go 有意避免了许多在其他语言中常见的复杂特性，如传统的类继承、操作符重载、复杂的泛型系统（早期）、宏、隐式类型转换等。这种克制，使得 Go 代码更易于阅读、理解和维护，尤其是在大型团队协作中，大大降低了沟通成本和因误解特性而引入错误的风险。</p>
<h2>从“百倍重力”到“一倍重力”：迁移者的幸福感源泉</h2>
<p>那位从 Scala 转到 Go 的开发者所描述的“从100倍重力训练环境出来，到了只有1倍重力的地方”那种“如释重负”的感觉，道出了许多从复杂语言或生态迁移到 Go 的开发者的心声。他们厌倦了：</p>
<ul>
<li><strong>“魔法”背后的不可预测性：</strong> 一些语言的高级特性或框架虽然能在特定场景下提供便利，但也可能隐藏了复杂的实现细节，使得程序的行为难以预测，调试如同“探案”。</li>
<li><strong>“体操”般的性能调优和依赖管理：</strong> 正如他所抱怨的：“浪费时间搞依赖管理，做 JVM 调优以榨取性能根本不值得。”</li>
<li><strong>冗长的学习曲线和高昂的心智维护成本。</strong></li>
</ul>
<p>Go 的出现，让他们卸下了这些沉重的“认知负荷”。他们不再需要花费大量精力去理解语言本身的复杂性或与庞大而笨重的生态系统搏斗，而是可以将精力聚焦在业务逻辑和解决实际问题上。这种“解放感”，是 Go 赋予迁移者的最直接的幸福感。</p>
<h2>工具链的“无痛体验”：“它就是好用！”</h2>
<p>除了语言本身的简洁，Go 语言<strong>开箱即用、体验极佳的工具链</strong>也是其备受赞誉的核心原因之一，是开发者“爽感”的重要来源。</p>
<p>原帖作者特别提到：“工具就是好用（尤其是在 Nvim 里）”。评论区的另一位开发者也表示：“Go 的工具链是我最喜欢的部分，我从不与之‘顶牛’。” 还有开发者在对比了过去维护复杂构建镜像（如 dockcross toolchain）的痛苦经历后，对 Go 工具链的优秀感到“疯狂”。</p>
<p>这种“不顶牛”、“不折腾”的工具链体验，体现在：</p>
<ul>
<li><strong>极快的编译速度：</strong> 使得开发迭代和反馈循环非常迅速。</li>
<li><strong>统一且无需配置的构建系统 (go build)：</strong> 告别了 Makefile、Maven、Gradle、Webpack 等复杂构建工具的学习和配置成本。</li>
<li><strong>内置的代码格式化 (gofmt) 和静态检查 (go vet)：</strong> 保证了团队代码风格的一致性和早期问题的发现。</li>
<li><strong>简洁高效的包管理 (go mod)：</strong> 解决了早期 Go 版本在依赖管理上的痛点，提供了清晰、可靠的依赖管理方案。</li>
<li><strong>强大的语言服务器协议 (LSP) 支持 (gopls)：</strong> 为各种编辑器（如 VS Code, Neovim, Goland）提供了流畅、智能的编码辅助体验。</li>
<li><strong>简单直接的测试框架 (go test)：</strong> 内置支持单元测试、基准测试、示例测试，易于上手和集成。</li>
</ul>
<p>正是这些设计精良、高度整合的工具，让 Go 开发者能够拥有一个“丝滑”的开发体验，将精力从繁琐的工具配置和环境问题中解放出来。</p>
<h2>Go 的务实主义与工程效率：为解决问题而生</h2>
<p>Go 语言从诞生之初，就带有强烈的<strong>务实主义和工程导向</strong>。它的设计目标之一，就是为了提高大型软件项目（尤其是在 Google 内部）的开发效率和可维护性。</p>
<ul>
<li><strong>极其丰富的标准库：</strong> 正如发帖者所言的“shit ton of stdlib”（极其丰富的标准库），Go 强大的标准库覆盖了网络编程、并发处理、数据编解码、加密、I/O 操作等众多领域，极大地减少了对外部第三方库的依赖，降低了项目的复杂性和潜在的供应链风险。</li>
<li><strong>原生可执行文件，简化部署：</strong> Go 程序通常被编译成单个静态链接的可执行文件，不依赖外部运行时（如 JVM、Python解释器等），使得部署过程极其简单，非常契合现代云原生和容器化部署的趋势。</li>
</ul>
<p>这些特性共同构成了 Go 在工程实践中的核心竞争力，使其成为构建网络服务、微服务、CLI 工具、基础设施软件等领域的理想选择。</p>
<h2>小结：简单不是简陋，而是深思熟虑的强大</h2>
<p>回到最初的问题：为什么 Go 语言的“简单之美”能让开发者直呼过瘾？</p>
<p>因为这种“简单”并非功能的缺失或设计的草率，而是<strong>一种深思熟虑的选择，一种对复杂性的克制，一种对开发者体验的极致追求。</strong> 它将“简单留给用户，将复杂留给自己（语言和工具链的设计者）”的理念贯彻到底。</p>
<p>Go 的魅力，在于它剔除了不必要的枝蔓，回归到编程的本质——清晰地表达逻辑，高效地解决问题。它让开发者能够以一种更接近直觉的方式去构建事物，而无需在抽象的迷宫中苦苦挣扎。</p>
<p>在这个日益复杂的世界里，Go 语言提供的这种“简单”和“直接”，本身就是一种强大的力量。它让我们能够更快地将想法付诸实践，更专注于创造价值，并在这个过程中享受到纯粹的构建乐趣。</p>
<p>这或许就是为什么，越来越多的开发者，在体验过 Go 语言带来的畅快之后，会由衷地感叹一句：“爽就完了！”</p>
<hr />
<p><strong>聊一聊，也帮个忙：</strong></p>
<ul>
<li><strong>你最喜欢 Go 语言的哪个“简单”特性？它在你的工作中带来了哪些便利和“爽”点？</strong></li>
<li><strong>你是否也有过从其他“复杂”语言或技术栈迁移到 Go 后，感到“如释重负”、“直呼过瘾”的经历？</strong></li>
<li><strong>除了文中提到的，你认为 Go 语言还有哪些让人“一旦上手，爱不释手”的魅力？</strong></li>
</ul>
<p>欢迎在<strong>评论区</strong>留下你的经验、思考和“爽点”！如果你觉得这篇文章道出了你对 Go 的喜爱，也请<strong>转发给你身边的 Gopher 朋友们</strong>，让更多人了解 Go 的“简单之美”！</p>
<p><strong>想与我进行更深入的 Go 语言设计哲学、工程实践与 AI 技术交流吗？</strong> 欢迎加入我的<strong>“Go &amp; AI 精进营”知识星球</strong>。</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-and-ai-tribe-zsxq-small-card.jpg" alt="img{512x368}" /></p>
<p>我们星球见！</p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/06/12/grog-brain-heaven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>“Rustacean”胚胎 vs “Gopher”胚胎：假如用技术栈测“人格”，你会是哪一款？</title>
		<link>https://tonybai.com/2025/06/07/nucleus-embryo/</link>
		<comments>https://tonybai.com/2025/06/07/nucleus-embryo/#comments</comments>
		<pubDate>Sat, 07 Jun 2025 12:08:56 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[ArchLinux]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[JetBrains]]></category>
		<category><![CDATA[macos]]></category>
		<category><![CDATA[NeoVim]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[Rustacean]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vscode]]></category>
		<category><![CDATA[并发]]></category>
		<category><![CDATA[接口]]></category>
		<category><![CDATA[测试]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4799</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/06/07/nucleus-embryo 大家好，我是Tony Bai。 最近，一张名为 “Nucleus Embryo” 的神秘图片在开发者圈子里悄然流传，引发了大家会心一笑（可能还带有一丝“我懂的”的复杂表情）。这张图煞有介事地对比了两个假想的“胚胎”——Embryo 1 和 Embryo 2——据称它们在“出厂设置”时，就已预装了不同的“技术基因”。 乍一看，这图表做得还挺像那么回事：有“Autism (自闭症倾向)”、“ADHD (多动症倾向)”、“Gender Dysphoria (性别焦虑倾向)”这些不明觉厉的百分点，还有看似严谨的“IQ (智商)”点数。但定睛一瞧，嘿，这“Language (编程语言)”、“Editor (编辑器)”、“OS (操作系统)”一栏，赫然出现了我们熟悉的 Rust、Go、VS Code (或类似现代IDE)、Neovim (或Vim)、Arch Linux 和 macOS 的 Logo！ 这显然是一张充满网络 Meme 精神的“恶搞图”，将复杂的人类特征与纯粹的技术偏好进行了一番天马行空的“强行配对”。 今天，我们就本着“纯属娱乐，请勿当真”的精神，来趣味解读一下，假如用技术栈来“测人格”，这两个“胚胎”分别代表了哪一款开发者“出厂画像”？而你，又更接近哪一款呢？ (郑重声明：以下解读纯属借助AI进行的基于网络 Meme 的趣味联想和对技术社区刻板印象的调侃，不代表任何科学观点，更不涉及对任何人群的评价或歧视。请大家在这个闲暇周末轻松阅读，切勿对号入座或上纲上线！) Embryo 1 号：“硬核掌控者”画像？ 让我们来看看 Embryo 1 号的“技术基因配置”： Language: Rust Editor: VS Code (或其抽象变体/同类现代IDE) OS: Arch Linux 如果非要给这个配置画个像，它可能散发着一股浓浓的“硬核玩家”和“掌控一切”的气息： [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/nucleus-embryo-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/06/07/nucleus-embryo">本文永久链接</a> &#8211; https://tonybai.com/2025/06/07/nucleus-embryo</p>
<p>大家好，我是Tony Bai。</p>
<p>最近，一张名为 “Nucleus Embryo” 的神秘图片在开发者圈子里悄然流传，引发了大家会心一笑（可能还带有一丝“我懂的”的复杂表情）。这张图煞有介事地对比了两个假想的“胚胎”——Embryo 1 和 Embryo 2——据称它们在“出厂设置”时，就已预装了不同的“技术基因”。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/nucleus-embryo-2.jpg" alt="" /></p>
<p>乍一看，这图表做得还挺像那么回事：有“Autism (自闭症倾向)”、“ADHD (多动症倾向)”、“Gender Dysphoria (性别焦虑倾向)”这些不明觉厉的百分点，还有看似严谨的“IQ (智商)”点数。但定睛一瞧，嘿，这“Language (编程语言)”、“Editor (编辑器)”、“OS (操作系统)”一栏，赫然出现了我们熟悉的 Rust、Go、VS Code (或类似现代IDE)、Neovim (或Vim)、Arch Linux 和 macOS 的 Logo！</p>
<p><strong>这显然是一张充满网络 Meme 精神的“恶搞图”，将复杂的人类特征与纯粹的技术偏好进行了一番天马行空的“强行配对”。</strong> 今天，我们就本着“纯属娱乐，请勿当真”的精神，来趣味解读一下，假如用技术栈来“测人格”，这两个“胚胎”分别代表了哪一款开发者“出厂画像”？而你，又更接近哪一款呢？</p>
<p><strong>(郑重声明：以下解读纯属借助AI进行的基于网络 Meme 的趣味联想和对技术社区刻板印象的调侃，不代表任何科学观点，更不涉及对任何人群的评价或歧视。请大家在这个闲暇周末轻松阅读，切勿对号入座或上纲上线！)</strong></p>
<h2>Embryo 1 号：“硬核掌控者”画像？</h2>
<p>让我们来看看 Embryo 1 号的“技术基因配置”：</p>
<ul>
<li><strong>Language: Rust</strong></li>
<li><strong>Editor: VS Code (或其抽象变体/同类现代IDE)</strong></li>
<li><strong>OS: Arch Linux</strong></li>
</ul>
<p>如果非要给这个配置画个像，它可能散发着一股浓浓的“硬核玩家”和“掌控一切”的气息：</p>
<ul>
<li><strong>Rust 语言：</strong> 以其对内存安全、并发性能的极致追求和陡峭的学习曲线著称。选择 Rust 的开发者，往往被认为是对系统底层有深入理解、不畏惧复杂性、追求代码极致性能和安全性的“屠龙勇士”。他们可能热衷于讨论生命周期、所有权、借用检查，并以编写出“零成本抽象”的代码为荣。</li>
<li><strong>VS Code (或类似现代IDE)：</strong> 虽然图中 Logo 比较抽象，但整体风格偏向现代、功能丰富的集成开发环境。这表明 Embryo 1 号在追求硬核的同时，也懂得利用现代工具提升开发体验，追求效率与功能的平衡。</li>
<li><strong>Arch Linux：</strong> 一个以“Keep It Simple, Stupid” (KISS) 和用户中心为理念，但需要用户从头构建和配置的 Linux 发行版。选择 Arch Linux 的用户，通常被认为是喜欢完全掌控自己的操作系统、不介意“折腾”、动手能力极强的 Linux 极客。</li>
</ul>
<p><strong>趣味解读 Embryo 1 号“人格”标签（纯属虚构，仅供娱乐）：</strong></p>
<ul>
<li><strong>优点：</strong> 追求极致、严谨细致、底层功力深厚、动手能力强、乐于探索。</li>
<li><strong>“萌点”/“槽点”：</strong> 可能会对“不够安全”、“不够高效”的代码嗤之鼻用鼻孔；热衷于向你安利 Arch Linux 并告诉你“编译大法好”；电脑上可能有无数个自己编译的工具链。</li>
<li><strong>口头禅（猜想）：</strong> “你的代码 unsafe 了吗？”、“这不符合 Rustacean 的精神！”、“Manjaro发行版？那是给新手玩的！”</li>
</ul>
<h2>Embryo 2 号：“务实效率派”画像？</h2>
<p>接下来，我们看看 Embryo 2 号的“出厂配置”：</p>
<ul>
<li><strong>Language: Go</strong></li>
<li><strong>Editor: Neovim (或 Vim)</strong></li>
<li><strong>OS: macOS</strong></li>
</ul>
<p>这个配置组合，则可能描绘出一位更注重简洁、实用和开发效率的“务实派”开发者：</p>
<ul>
<li><strong>Go 语言：</strong> 以其简洁的语法、高效的编译速度、强大的并发模型和完善的工具链闻名。选择 Go 的开发者，通常被认为是务实的工程派，他们更关注如何快速、可靠地构建可维护的系统，尤其在云原生、微服务、分布式系统领域得心应手。</li>
<li><strong>Neovim (或 Vim)：</strong> 一款高度可定制、键盘驱动、以高效文本编辑著称的编辑器。选择 Neovim/Vim 的开发者，往往追求极致的编辑效率和个性化的工作流，他们可能对鼠标“不屑一顾”，并能熟练地运用各种快捷键和插件组合。</li>
<li><strong>macOS：</strong> 一个以用户体验、设计美感和 Unix 友好性著称的操作系统。选择 macOS 的 Gopher，可能既看重其稳定易用的图形界面，也喜欢其背后强大的 Unix 内核和开发工具生态。</li>
</ul>
<p><strong>趣味解读 Embryo 2 号“人格”标签（纯属虚构，仅供娱乐）：</strong></p>
<ul>
<li><strong>优点：</strong> 简洁高效、务实专注、工程能力强、注重工具链整合。</li>
<li><strong>“萌点”/“槽点”：</strong> 可能会对“过度设计”、“不必要的复杂性”表示不解；坚信“少即是多，接口就是力量”；熟练掌握各种 hjkl 操作，并试图在一切应用中寻找 Vim 模式。</li>
<li><strong>口头禅（猜想）：</strong> “一个 goroutine 搞定！”、“这个接口设计不 Go！”、“JetBrains IDE？太重了，我用 Neovim/Vim 就够了！”</li>
</ul>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<h2>敏感标签的“荒谬”与 IQ 的“一视同仁”</h2>
<p>当然，这张图中除了技术栈，还有一些关于 Autism、ADHD、Gender Dysphoria 的“百分点”和 IQ 的“点数”。<strong>我们必须再次强调，将这些复杂且严肃的个体特征与技术选择简单粗暴地关联起来，是极度荒谬和不负责任的。</strong> 每个人的生理和心理状况都是独特的，不应被任何标签所定义，更不应与他们使用的工具挂钩。</p>
<p>有趣的是，在这张充满“偏见”的图中，两个“胚胎”的 IQ 点数却是相同的（都是+4）。这或许是制图者在用一种黑色幽默的方式暗示：<strong>无论你选择哪种技术栈，你的基础智力水平可能都差不多；或者，技术偏好与所谓的“智商高低”并无直接关联。</strong> 这点倒是值得我们深思。</p>
<h2>技术的本质是工具，标签仅供一笑</h2>
<p>说到底，这张 “Nucleus Embryo” 图，更像是一面映照技术社区中各种“梗”和“刻板印象”的哈哈镜。它用一种夸张的方式，触碰了我们潜意识中对不同技术群体的一些模糊认知。</p>
<p>编程语言、编辑器、操作系统，本质上都只是工具。选择使用哪种工具，更多的是基于个人偏好、项目需求、团队协作以及特定场景下的效率考量。<strong>没有任何一种技术栈组合能够定义一个人的全部，更不能决定其“人格”或“价值”。</strong></p>
<p>所以，当我们看到这张图时，不妨一笑置之。你可以开玩笑地对号入座，或者和朋友们讨论一下自己心目中不同技术栈组合的“开发者画像”，但请务必记住：</p>
<ul>
<li><strong>这纯属娱乐，切勿当真。</strong></li>
<li><strong>尊重每一个人的技术选择和个体差异。</strong></li>
<li><strong>警惕任何形式的标签化和刻板印象。</strong></li>
</ul>
<p>技术的魅力在于其多样性和解决问题的能力。无论你是“Embryo 1 号”、“Embryo 2 号”，还是任何其他独特的技术栈组合的拥趸，最重要的是享受编码的乐趣，创造有价值的软件，并在这个过程中不断学习和成长。</p>
<hr />
<p><strong>聊一聊，纯属娱乐大调查！</strong></p>
<ul>
<li><strong>看完这张图和解读，你觉得自己更接近“Embryo 1 号”还是“Embryo 2 号”的“技术基因”？或者你认为自己是哪种全新的“技术胚胎”？</strong></li>
<li><strong>在你心目中，使用特定编程语言/编辑器/操作系统的开发者，通常有哪些有趣的“刻板印象”？（欢迎在评论区开启“吐槽”模式，但请保持友好！）</strong></li>
<li><strong>你认为技术社区中，除了图上提到的，还有哪些常见的“鄙视链”或“部落文化”现象？我们该如何消解它们？</strong></li>
</ul>
<p>欢迎在<strong>评论区</strong>踊跃发言，分享你的“技术人格”自画像和趣味观察！如果你觉得这篇文章让你会心一笑，也请<strong>转发给你身边的开发者朋友们</strong>，一起加入这场轻松愉快的“技术对对碰”！</p>
<hr />
<p><strong>微专栏推荐：征服 Go 并发测试</strong></p>
<p>想彻底告别并发测试的“噩梦”吗？我的全新微专栏 <strong>《征服 Go 并发测试》</strong>（共三篇）现已上线！</p>
<p>本系列深入剖析并发测试痛点、testing/synctest 的设计原理与 API，并提供丰富的实战案例。助你轻松驾驭并发测试，写出更稳健的 Go 应用！</p>
<p><strong>微信扫码订阅，即刻解锁并发测试新境界！</strong></p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-concurrent-test-qr.png" alt="" /></p>
<p><strong>更多微专栏，敬请期待！</strong> 对后续选题（如 Go 性能优化、AI 与 Go 结合等）有何期待或建议？欢迎在<strong>留言区</strong>畅所欲言，一起打造更精彩的内容！</p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/06/07/nucleus-embryo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gopher的Rust第一课：建立Rust开发环境</title>
		<link>https://tonybai.com/2024/05/10/gopher-rust-first-lesson-setup-dev-env/</link>
		<comments>https://tonybai.com/2024/05/10/gopher-rust-first-lesson-setup-dev-env/#comments</comments>
		<pubDate>Fri, 10 May 2024 13:35:25 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[cargo]]></category>
		<category><![CDATA[coc.nvim]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go1.22]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[GOPROXY]]></category>
		<category><![CDATA[LSP]]></category>
		<category><![CDATA[nightly]]></category>
		<category><![CDATA[playground]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[rust-analyzer]]></category>
		<category><![CDATA[rust-toolchain.toml]]></category>
		<category><![CDATA[rust1.77.0]]></category>
		<category><![CDATA[rustc]]></category>
		<category><![CDATA[RustRover]]></category>
		<category><![CDATA[rustup]]></category>
		<category><![CDATA[RUSTUP_TOOLCHAIN]]></category>
		<category><![CDATA[stable]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vscode]]></category>
		<category><![CDATA[开发环境]]></category>
		<category><![CDATA[滚动发布]]></category>
		<category><![CDATA[语言服务器]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4164</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2024/05/10/gopher-rust-first-lesson-setup-dev-env 经过上一章的对Rust诞生演化的了解以及设计哲学的探讨后，如果你依然决定继续Rust编程学习之旅，那么欢迎你和我一起正式走进Rust学习和实践的课堂。 编程不是“纸上谈兵”，它是一门实践的艺术。编程语言的学习离不开动手实践，因此学习任何一门编程语言的第一步都是要拥有一个这门编程语言的开发环境，这样我们才可以动手编码，理论与实践结合，不仅加速学习效率，还能取得更好的学习效果。 在这一章中我们就先来学习下如何安装和配置Rust开发环境。如果你的机器上还没有Rust开发环境，那么就请跟我一起选择一种适合你的Rust安装方法吧。 第一步，我们先来挑一个合适的Rust版本。 2.1 选择Rust版本 2.1.1 Go与Rust发布版本与节奏的对比 在《Go语言第一课专栏》讲解如何建立Go开发环境时，我首先讲解的也是选择Go版本。我们知道Go一年发布两次大版本，分别是每年的2月和8月，并且Go核心团队只对最近的两个大版本提供support。在处于support时间窗口中的时候，Go核心团队会发布一些补丁版本，修正及少量的严重问题或安全漏洞。比如Go 1.22版本是2024年2月份发布的，到2024年4月中旬，Go 1.22的最新补丁版本已经到了Go 1.22.2了。下图展示了Go版本发布的节奏以及support的窗口： 在Go中，我们可以选择最新稳定版（比如图中的Go 1.22.2）和次新稳定版（比如图中的1.21.8），这两个是Go社区选择最多的。此外，也可以选择某个特定的稳定版（因某种特殊原因，被阻塞在该版本上）以及tip版，其中tip版（master分支上的最新commit版本）主要用于体验最新的、尚未发布的功能特性或问题修复，或是contributor多使用tip版。 Rust的版本发布节奏与Go完全不同，因此Rust版本的选择逻辑与Go相比也就有所不同。下图展示了Rust的版本发布方法与节奏： 我们看到：Rust采用“6周一个稳定版”的滚动发布节奏，并且有三类版本：稳定版(stable)、公测版(beta)和nightly版，分别对应的是stable分支、beta分支和master分支。三个版本间是关联紧密的。 以图中的rust 1.77.0的发布为例，rust 1.77.0稳定版本的发布动作是这样的： 基于当前beta分支(其实就是1.77.0 beta)创建新的stable分支，并tag 1.77.0； 基于当前master分支(nightly版本)创建新的beta分支，并在新的beta分支上公测1.78.0版本，为六周后的1.78.0稳定版做准备； 而master分支上继续开发v1.79.0的新特性，并每天发布Nightly版本。 之后，原1.76.0稳定版便会从support窗口删除，1.77.0进入Support窗口。如果新发布的1.77.0有紧急或安全问题需要修复，则通过补丁(patch)版本进行，比如rust 1.77.1、1.77.2等。 Rust这种“稳定一版，公测一版，开发一版”的“三路并发”的滚动开发节奏，显然要比Go的“稳定一版，开发一版”的“两路并发”节奏要快上很多。不过，频繁的更新可能对某些用户来说是一个挑战，需要他们不断学习和适应新的变化。另外，较快的演进速度也可能导致一些不稳定因素，需要开发者更加谨慎地使用新功能特性。 2.1.2 Rust的三类版本 选择Rust版本根据自己的角色和面对的场合来进行： 对于大多数Rust开发者而言，最新的稳定版(stable)是最好和最明智的选择； 也有少部分因为各种特殊原因，可能阻塞在某个特定的稳定版上； Beta版contributor，或是想提前尝鲜下一个稳定版新特性的开发人员，可以临时使用beta版本； Nightly版，主要针对的也是contributor，或是想临时尝鲜最新不稳定功能特性的开发人员。 Rust提供的安装和升级工具rustup可以灵活的在三类版本间切换： rustup default beta rustup default nightly rustup default stable 切换后，rustup会自动同步该类版本到最新版： $rustup default beta info: syncing channel updates [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2024/05/10/gopher-rust-first-lesson-setup-dev-env">本文永久链接</a> &#8211; https://tonybai.com/2024/05/10/gopher-rust-first-lesson-setup-dev-env</p>
<p>经过上一章的对<a href="https://tonybai.com/2024/04/22/gopher-rust-first-lesson-all-about-rust/">Rust诞生演化的了解以及设计哲学的探讨</a>后，如果你依然决定继续Rust编程学习之旅，那么欢迎你和我一起正式走进Rust学习和实践的课堂。</p>
<p>编程不是“纸上谈兵”，它是一门实践的艺术。编程语言的学习离不开动手实践，因此学习任何一门编程语言的第一步都是要拥有一个这门编程语言的开发环境，这样我们才可以动手编码，理论与实践结合，不仅加速学习效率，还能取得更好的学习效果。</p>
<p>在这一章中我们就先来学习下如何安装和配置Rust开发环境。如果你的机器上还没有Rust开发环境，那么就请跟我一起选择一种适合你的Rust安装方法吧。</p>
<p>第一步，我们先来挑一个合适的Rust版本。</p>
<h2>2.1 选择Rust版本</h2>
<h3>2.1.1 Go与Rust发布版本与节奏的对比</h3>
<p>在<a href="http://gk.link/a/10AVZ">《Go语言第一课专栏》</a>讲解如何建立Go开发环境时，我首先讲解的也是选择Go版本。我们知道Go一年发布两次大版本，分别是每年的2月和8月，并且Go核心团队只对最近的两个大版本提供support。在处于support时间窗口中的时候，Go核心团队会发布一些补丁版本，修正及少量的严重问题或安全漏洞。比如<a href="https://tonybai.com/2024/02/18/some-changes-in-go-1-22/">Go 1.22版本</a>是2024年2月份发布的，到2024年4月中旬，Go 1.22的最新补丁版本已经到了Go 1.22.2了。下图展示了Go版本发布的节奏以及support的窗口：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-2.png" alt="" /></p>
<p>在Go中，我们可以选择最新稳定版（比如图中的Go 1.22.2）和次新稳定版（比如图中的1.21.8），这两个是Go社区选择最多的。此外，也可以选择某个特定的稳定版（因某种特殊原因，被阻塞在该版本上）以及tip版，其中tip版（master分支上的最新commit版本）主要用于体验最新的、尚未发布的功能特性或问题修复，或是contributor多使用tip版。</p>
<p>Rust的版本发布节奏与Go完全不同，因此Rust版本的选择逻辑与Go相比也就有所不同。下图展示了Rust的版本发布方法与节奏：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-3.png" alt="" /></p>
<p>我们看到：Rust采用“6周一个稳定版”的滚动发布节奏，并且有三类版本：稳定版(stable)、公测版(beta)和nightly版，分别对应的是stable分支、beta分支和master分支。三个版本间是关联紧密的。</p>
<p>以图中的<a href="https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html">rust 1.77.0的发布</a>为例，rust 1.77.0稳定版本的发布动作是这样的：</p>
<ul>
<li>基于当前beta分支(其实就是1.77.0 beta)创建新的stable分支，并tag 1.77.0；</li>
<li>基于当前master分支(nightly版本)创建新的beta分支，并在新的beta分支上公测1.78.0版本，为六周后的1.78.0稳定版做准备；</li>
<li>而master分支上继续开发v1.79.0的新特性，并每天发布Nightly版本。</li>
</ul>
<p>之后，原1.76.0稳定版便会从support窗口删除，1.77.0进入Support窗口。如果新发布的1.77.0有紧急或安全问题需要修复，则通过补丁(patch)版本进行，比如rust 1.77.1、1.77.2等。</p>
<p>Rust这种“稳定一版，公测一版，开发一版”的“三路并发”的滚动开发节奏，显然要比Go的“稳定一版，开发一版”的“两路并发”节奏要快上很多。不过，频繁的更新可能对某些用户来说是一个挑战，需要他们不断学习和适应新的变化。另外，较快的演进速度也可能导致一些不稳定因素，需要开发者更加谨慎地使用新功能特性。</p>
<h3>2.1.2 Rust的三类版本</h3>
<p>选择Rust版本根据自己的角色和面对的场合来进行：</p>
<ul>
<li>对于大多数Rust开发者而言，最新的稳定版(stable)是最好和最明智的选择；</li>
<li>也有少部分因为各种特殊原因，可能阻塞在某个特定的稳定版上；</li>
<li>Beta版contributor，或是想提前尝鲜下一个稳定版新特性的开发人员，可以临时使用beta版本；</li>
<li>Nightly版，主要针对的也是contributor，或是想临时尝鲜最新不稳定功能特性的开发人员。</li>
</ul>
<p>Rust提供的安装和升级工具<a href="https://rustup.rs/">rustup</a>可以灵活的在三类版本间切换：</p>
<pre><code>rustup default beta
rustup default nightly
rustup default stable
</code></pre>
<p>切换后，rustup会自动同步该类版本到最新版：</p>
<pre><code>$rustup default beta
info: syncing channel updates for 'beta-x86_64-apple-darwin'
info: latest update on 2024-04-11, rust version 1.78.0-beta.6 (27011d5dc 2024-04-09)
... ...
</code></pre>
<p>确定了要使用的Rust版本后，我们接下来就来看看究竟如何安装Rust。</p>
<h2>2.2 安装Rust</h2>
<h3>2.2.1 使用rustup安装</h3>
<p>和Go尽可以通过安装包或下载预编译二进制包进行首次安装不同，Rust官方提供了统一的Rust安装、管理和升级工具- <a href="https://rustup.rs">rustup</a>。 Rust官方在Linux和macOS上提供了“curl | sh”的一键式安装命令：</p>
<pre><code>$curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
</code></pre>
<p>我们以Linux下安装rustup为例，看一下执行上面命令的过程和最终结果：</p>
<pre><code>$curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /root/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /root/.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:

  /root/.cargo/bin

This path will then be added to your PATH environment variable by
modifying the profile files located at:

  /root/.profile
  /root/.bashrc

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:

   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation

&gt; // 敲击回车

info: profile set to 'default'
info: default host triple is x86_64-unknown-linux-gnu
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: latest update on 2024-04-09, rust version 1.77.2 (25ef9e3d8 2024-04-09)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 14.9 MiB /  14.9 MiB (100 %)   3.7 MiB/s in  3s ETA:  0s
info: installing component 'rust-std'
 24.3 MiB /  24.3 MiB (100 %)   8.2 MiB/s in  2s ETA:  0s
info: installing component 'rustc'
 60.3 MiB /  60.3 MiB (100 %)   9.6 MiB/s in  6s ETA:  0s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-unknown-linux-gnu'

  stable-x86_64-unknown-linux-gnu installed - rustc 1.77.2 (25ef9e3d8 2024-04-09)

Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, you need to source
the corresponding env file under $HOME/.cargo.

This is usually done by running one of the following (note the leading DOT):
. "$HOME/.cargo/env"            # For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish"  # For fish
</code></pre>
<p>接下来按照提示执行下面命令，使得Rust相关的环境变量生效：</p>
<pre><code>$. "$HOME/.cargo/env"
$which rustup
/root/.cargo/bin/rustup
</code></pre>
<p>. “$HOME/.cargo/env”这行代码也被追加到/root/.bashrc文件中，如果新启动一个terminal窗口，这行shell配置也会被执行，即rustup的环境变量也生效。</p>
<p>查看一下安装的rustup的版本：</p>
<pre><code>$rustup -V
rustup 1.27.0 (bbb9276d2 2024-03-08)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.77.2 (25ef9e3d8 2024-04-09)`
</code></pre>
<p>同时我们看到：首次安装rustup时，如果选择“standard installation”，rustup会为我们安装一个最新的Rust stable版本，这里是1.77.2，我们可以通过rustup show命令查看已安装的rust工具链：</p>
<pre><code>$rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /root/.rustup

stable-x86_64-unknown-linux-gnu (default)
rustc 1.77.2 (25ef9e3d8 2024-04-09)
</code></pre>
<p>除此之外，rustup还在你的系统中都做了啥呢？我们下面来探索一下。</p>
<h4>2.2.1.1 安装后的探索</h4>
<p>根据rustup在安装过程中的提示，有两个路径是需要重点关注的。</p>
<p>一个就是\$HOME/.cargo，rustup将.cargo/bin加入到了\$PATH变量下，我们来看看.cargo下都有哪些目录和文件：</p>
<pre><code>$tree -F .cargo
.cargo
|-- bin/
|   |-- cargo*
|   |-- cargo-clippy*
|   |-- cargo-fmt*
|   |-- cargo-miri*
|   |-- clippy-driver*
|   |-- rls*
|   |-- rust-analyzer*
|   |-- rustc*
|   |-- rustdoc*
|   |-- rustfmt*
|   |-- rust-gdb*
|   |-- rust-gdbgui*
|   |-- rust-lldb*
|   `-- rustup*
`-- env
</code></pre>
<p>.cargo下主要的目录就是bin，这里存放了日常rust开发时在命令行使用的所有cli命令，包括cargo(构建管理工具)、rustc(编译器)、rustdoc、rustfmt以及rustup自身等。</p>
<p>另外一个更值得关注的目录就是\$HOME/.rustup目录，这个目录下的内容较多，我们通过tree命令查看的结果如下：</p>
<pre><code>$tree -F -L 3  .rustup
.rustup
|-- downloads/
|-- settings.toml
|-- tmp/
|-- toolchains/
|   `-- stable-x86_64-unknown-linux-gnu/
|       |-- bin/
|       |-- etc/
|       |-- lib/
|       |-- libexec/
|       `-- share/
`-- update-hashes/
    `-- stable-x86_64-unknown-linux-gnu
</code></pre>
<p>settings.toml是一个rustup配置文件，它的内容如下：</p>
<pre><code>$cat .rustup/settings.toml
default_toolchain = "stable-x86_64-unknown-linux-gnu"
profile = "default"
version = "12"

[overrides]
</code></pre>
<p>这里的default_toolchain指示了当前默认使用的工具链版本为stable-x86_64-unknown-linux-gnu。这个版本也是一个target，Rust支持的不同平台上的target以及含义如下图：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-4.png" alt="" /></p>
<p>.rustup下的另外一个值得注意的目录是toolchains，它下面存放了安装到本地的所有版本的toolchain，上面由于只安装了stable的最新版本，因此当前toolchains下只有一个stable-x86_64-unknown-linux-gnu目录。</p>
<p>值得注意的是.rustup中存储了rust工具链的所有内容，因此它的空间占用也着实可观：</p>
<pre><code>$ du -sh .rustup
1.2G    .rustup
</code></pre>
<p>现在我们来切换默认版本到beta：</p>
<pre><code>$rustup default beta
info: syncing channel updates for 'beta-x86_64-unknown-linux-gnu'
info: latest update on 2024-04-11, rust version 1.78.0-beta.6 (27011d5dc 2024-04-09)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 15.1 MiB /  15.1 MiB (100 %)   3.4 MiB/s in  3s ETA:  0s
info: installing component 'rust-std'
 24.2 MiB /  24.2 MiB (100 %)   9.3 MiB/s in  2s ETA:  0s
info: installing component 'rustc'
 63.5 MiB /  63.5 MiB (100 %)   9.6 MiB/s in  6s ETA:  0s
info: installing component 'rustfmt'
info: default toolchain set to 'beta-x86_64-unknown-linux-gnu'

  beta-x86_64-unknown-linux-gnu installed - rustc 1.78.0-beta.6 (27011d5dc 2024-04-09)
</code></pre>
<p>我们看到rustup会自动下载安装最新的beta版本，安装后，我们再执行rustc -V来查看当前版本，我们发现结果已经变为了下面这样：</p>
<pre><code>$ rustc -V
rustc 1.78.0-beta.6 (27011d5dc 2024-04-09)
</code></pre>
<p>这里值得注意的是，虽然我们执行的rustc是.cargo/bin/rustc，但.cargo/bin/rustc有些类似于一个指针，真正执行的是其“指向”的某个工具链版本的rustc，我们可以使用rustup which rustc来查看究竟执行的是哪个rustc：</p>
<pre><code>$ rustup which rustc
/root/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/bin/rustc
</code></pre>
<p>此时，.rustup目录下面发生了怎样的变化呢？我们来看看：</p>
<pre><code>$ tree -F -L 3  .rustup
.rustup
|-- downloads/
|-- settings.toml
|-- tmp/
|-- toolchains/
|   |-- beta-x86_64-unknown-linux-gnu/
|   |   |-- bin/
|   |   |-- etc/
|   |   |-- lib/
|   |   |-- libexec/
|   |   `-- share/
|   `-- stable-x86_64-unknown-linux-gnu/
|       |-- bin/
|       |-- etc/
|       |-- lib/
|       |-- libexec/
|       `-- share/
`-- update-hashes/
    |-- beta-x86_64-unknown-linux-gnu
    `-- stable-x86_64-unknown-linux-gnu
</code></pre>
<p>我们看到toolchains下面多了一个beta-x86_64-unknown-linux-gnu目录，存放的就是刚刚安装的beta最新版本工具链。</p>
<p>现在我们在用rustup show命令查看已安装的rust工具链，其结果如下：</p>
<pre><code>$rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /root/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu
beta-x86_64-unknown-linux-gnu (default)

active toolchain
----------------

beta-x86_64-unknown-linux-gnu (default)
rustc 1.78.0-beta.6 (27011d5dc 2024-04-09)
</code></pre>
<p>现在，我们切换回stable版本，由于stable版本之前已经安装完毕，也就无需下载和安装过程了：</p>
<pre><code>$rustup default stable
info: using existing install for 'stable-x86_64-unknown-linux-gnu'
info: default toolchain set to 'stable-x86_64-unknown-linux-gnu'

  stable-x86_64-unknown-linux-gnu unchanged - rustc 1.77.2 (25ef9e3d8 2024-04-09)
</code></pre>
<h4>2.2.1.2 安装和使用特定版本rust工具链</h4>
<p>我们还可以使用rustup安装特定版本的rust工具链，比如通过下面的命令，我们安装stable版本的1.66.0：</p>
<pre><code>$ rustup install 1.66.0
info: syncing channel updates for '1.66.0-x86_64-unknown-linux-gnu'
info: latest update on 2022-12-15, rust version 1.66.0 (69f9c33d7 2022-12-12)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 19.0 MiB /  19.0 MiB (100 %)   4.4 MiB/s in  3s ETA:  0s
info: installing component 'rust-std'
 29.7 MiB /  29.7 MiB (100 %)   8.1 MiB/s in  3s ETA:  0s
info: installing component 'rustc'
 68.0 MiB /  68.0 MiB (100 %)  10.2 MiB/s in  6s ETA:  0s
info: installing component 'rustfmt'

  1.66.0-x86_64-unknown-linux-gnu installed - rustc 1.66.0 (69f9c33d7 2022-12-12)

info: checking for self-update
</code></pre>
<p>安装ok后，我们再来看看.rustup目录下的变化：</p>
<pre><code>$tree -F -L 3  .rustup
.rustup
|-- downloads/
|-- settings.toml
|-- tmp/
|-- toolchains/
|   |-- 1.66.0-x86_64-unknown-linux-gnu/
|   |   |-- bin/
|   |   |-- etc/
|   |   |-- lib/
|   |   |-- libexec/
|   |   `-- share/
|   |-- beta-x86_64-unknown-linux-gnu/
|   |   |-- bin/
|   |   |-- etc/
|   |   |-- lib/
|   |   |-- libexec/
|   |   `-- share/
|   `-- stable-x86_64-unknown-linux-gnu/
|       |-- bin/
|       |-- etc/
|       |-- lib/
|       |-- libexec/
|       `-- share/
`-- update-hashes/
    |-- 1.66.0-x86_64-unknown-linux-gnu
    |-- beta-x86_64-unknown-linux-gnu
    `-- stable-x86_64-unknown-linux-gnu
</code></pre>
<p>我们看到toolchains下面多了一个1.66.0-x86_64-unknown-linux-gnu，那我们如何使用新下载的1.66.0 stable版本呢？有几种方法，下面逐一介绍一下。</p>
<p>我们可以使用rust工具链的“plus语法”在命令行上指定要使用的工具链，这个语法对cargo、rustc等工具链中的命令行程序都适用：</p>
<pre><code>$ rustc +1.66.0 -V
rustc 1.66.0 (69f9c33d7 2022-12-12)
$ rustc +1.65.0 -V
error: toolchain '1.65.0-x86_64-unknown-linux-gnu' is not installed

$ cargo +1.66.0 -V
cargo 1.66.0 (d65d197ad 2022-11-15)
$ cargo +1.65.0 -V
error: toolchain '1.65.0-x86_64-unknown-linux-gnu' is not installed
</code></pre>
<blockquote>
<p>注：<a href="https://doc.rust-lang.org/cargo/">cargo</a>是Rust语言的官方构建系统和包管理器，它提供了一组命令行工具，可以自动化构建、测试和发布Rust项目。它还支持自动解析和下载依赖项，使得管理项目的依赖关系变得简单和可靠。Cargo是Rust生态系统中重要的工具之一，为开发者提供了高效和方便的开发体验。在后面的章节中我会详细介绍cargo。</p>
</blockquote>
<p>对于要使用特定版本进行构建的rust项目，我们可以通过rustup override来指定版本号。下面就是一个这样的例子：</p>
<pre><code>$cargo new hellorust
     Created binary (application) `hellorust` package
$cd hellorust/
$rustup override set 1.66.0
info: override toolchain for '/root/test/rust/hellorust' set to '1.66.0-x86_64-unknown-linux-gnu'
</code></pre>
<p>我们用cargo创建了一个新的hellorust项目，在hellorust项目下，我们执行rustup override来指定该项目使用1.66.0版本进行构建。</p>
<p>之后，我们分别在该项目目录下以及其他目录下执行rustc，我们看到输出结果如下：</p>
<pre><code>~/test/rust/hellorust$ rustc -V
rustc 1.66.0 (69f9c33d7 2022-12-12)
$ cd ..
~/test/rust$ rustc -V
rustc 1.77.2 (25ef9e3d8 2024-04-09)
</code></pre>
<p>rustc override的原理其实是在$HOME/.rustup/settings.toml文件中添加了一些内容：</p>
<pre><code>$cat .rustup/settings.toml
default_toolchain = "stable-x86_64-unknown-linux-gnu"
profile = "default"
version = "12"

[overrides]
"/root/test/rust/hellorust" = "1.66.0-x86_64-unknown-linux-gnu"
</code></pre>
<p>我们看到在overrides下新增了一条规则，指定了hellorust项目需要使用1.66.0-x86_64-unknown-linux-gnu这个工具链。</p>
<p>不过这种与本地路径紧耦合的配置方案并不是适合大范围协作，无法提交到git仓库中分享给其他人。</p>
<p>Rust还提供了另外一种override toolchain版本的方法，我们可以在hellorust项目的根目录下放置一个名为rust-toolchain.toml的文件，其内容如下：</p>
<pre><code>// rust-toolchain.toml

[toolchain]
channel = "1.66.0"
</code></pre>
<p>我们先执行rustup override unset将上面设置的override规则取消掉:</p>
<pre><code>$rustup override unset
info: override toolchain for '/root/test/rust/hellorust' removed
</code></pre>
<p>然后toolchain.toml就会生效了：</p>
<pre><code>// 在hellorust路径下
$rustc -V
rustc 1.66.0 (69f9c33d7 2022-12-12)
</code></pre>
<p>显然，这里涉及到了override的优先级顺序问题。Rust规定版本override的优先级顺序由高到低依次是：</p>
<ol>
<li>plus语法：“rustc +1.66.0 -V”</li>
<li>RUSTUP_TOOLCHAIN环境变量 (default: none)</li>
<li>rustup override命令</li>
<li>rust-toolchain.toml</li>
<li>默认toolchain</li>
</ol>
<h4>2.2.1.3  在Windows上安装Rust</h4>
<p>上述通过“curl|ssh”安装rustup，并通过rustup安装Rust工具链的方法是在Linux和macOS上安装Rust的主流方法，但在习惯于图形化安装的Windows上，略有变通。在Windows上，我们可以下载和安装一个名为<a href="https://static.rust-lang.org/rustup/dist/i686-pc-windows-gnu/rustup-init.exe">rustup-init.exe的程序</a>，它等价于其他os上的rustup，但可以交互式的引导用户安装。</p>
<p>由于手旁没有Windows环境，具体的安装过程这里就不详细说明了。</p>
<h3>2.2.2 离线安装包安装</h3>
<p>和Go一样，Rust也提供了离线安装包的安装方式，在<a href="https://forge.rust-lang.org/infra/other-installation-methods.html#standalone-installers">离线安装包下载页面</a>可以找到各个平台的多种文件格式（目前包括.tar.xz、.msi和.pkg）的离线安装包。</p>
<p>习惯在Windows上开发Rust程序的开发者可以直接下载和使用.msi来安装Rust开发环境。</p>
<h2>2.3 更新和卸载Rust</h2>
<p>使用rustup来更新和卸载Rust非常简单方便。</p>
<p>以更新stable版本为例，通过下面命令，我们就可以将本地的stable版本更新到最新stable版本。以我的macOS为例，我通过rustup将stable版本更新为最新的Rust 1.77.2：</p>
<pre><code>$rustup update stable
info: syncing channel updates for 'stable-x86_64-apple-darwin'
info: latest update on 2024-04-09, rust version 1.77.2 (25ef9e3d8 2024-04-09)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
 14.9 MiB /  14.9 MiB (100 %)   9.3 MiB/s in  1s ETA:  0s
info: downloading component 'rust-std'
 25.4 MiB /  25.4 MiB (100 %) 764.8 KiB/s in 12s ETA:  0s
info: downloading component 'rustc'
 54.9 MiB /  54.9 MiB (100 %)   8.6 MiB/s in  7s ETA:  0s
info: downloading component 'rustfmt'
  1.8 MiB /   1.8 MiB (100 %) 564.9 KiB/s in  3s ETA:  0s
info: removing previous version of component 'cargo'
info: removing previous version of component 'clippy'
info: removing previous version of component 'rust-docs'
info: removing previous version of component 'rust-std'
info: removing previous version of component 'rustc'
info: removing previous version of component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 14.9 MiB /  14.9 MiB (100 %)   4.2 MiB/s in  3s ETA:  0s
info: installing component 'rust-std'
 25.4 MiB /  25.4 MiB (100 %)  13.8 MiB/s in  2s ETA:  0s
info: installing component 'rustc'
 54.9 MiB /  54.9 MiB (100 %)  13.9 MiB/s in  4s ETA:  0s
info: installing component 'rustfmt'

  stable-x86_64-apple-darwin updated - rustc 1.77.2 (25ef9e3d8 2024-04-09) (from rustc 1.75.0 (82e1608df 2023-12-21))
... ...
</code></pre>
<p>通过更新的日志，我们看到rust的相关工具组件（比如cargo、rustfmt等）也得到了一并的更新。</p>
<p>Rust通过rustup提供了卸载Rust环境的命令：</p>
<pre><code>$rustup self uninstall

Thanks for hacking in Rust!

This will uninstall all Rust toolchains and data, and remove
$HOME/.cargo/bin from your PATH environment variable.

Continue? (y/N) _
</code></pre>
<p>我们看到：rustup会在控制台上与你进行一个确认继续的交互，确认你真的要卸载。如果你输入y并按Enter键继续，那么rustup会移除所有与Rust相关的文件，包括工具链、库、环境变量等。</p>
<p>如果你需要保留一些Rust版本，可以先运行rustup toolchain list，查看已安装的版本。然后用rustup toolchain uninstall命令单独卸载不需要的版本：</p>
<pre><code>$rustup toolchain uninstall 1.64-x86_64-apple-darwin
info: uninstalling toolchain '1.64-x86_64-apple-darwin'
info: toolchain '1.64-x86_64-apple-darwin' uninstalled
</code></pre>
<h2>2.4 配置Rust</h2>
<p>在<a href="http://gk.link/a/10AVZ">《Go语言第一课专栏》</a>讲解安装Go之后的配置时，我们主要提到了国内开发者要配置一个合适的GOPROXY。而Rust的各个站点都在合规访问范围内，我们安装Rust后无需做任何配置即可敞开使用Rust。</p>
<p>不过也有开发者觉得通过Rust官方下载crate慢，希望更换国内源，这种换源主要涉及的是cargo这个工具，我们后续学习Cargo时再来说明如何换源以及换哪个稳定的国内源。</p>
<h2>2.5 在线体验Rust</h2>
<p><a href="https://go.dev/play/">Go提供了在线的Go playground</a>可供尚未在本地安装Go环境的开发者体验Go语法，Go playground提供了三个版本：最新稳定版、次新稳定版以及tip版本，并且可以将代码通过短连接分享给其他开发者，十分方便。</p>
<p>这方面Rust也不逞多让，提供了功能足够丰富的<a href="https://play.rust-lang.org">Rust Playground</a>：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-5.png" alt="" /></p>
<p>在这里，我们可以选择Rust的版本：stable、beta还是nightly；可以选择编译模式，是debug还是release；可以选择Rust edition；可以选择执行一些工具，比如rustfmt；可以选择执行的命令：Run、Build、Test、MIR等。</p>
<p>不过，Rust、Go的playground毕竟只是用于在线体验的站点，他们具有共同的一些局限，比如：不支持第三方依赖，无法做复杂的多源文件项目的体验。</p>
<h2>2.6 编辑器与IDE</h2>
<p>对于开发人员来说，一门语言的开发环境不仅包含语言官方提供的编译器以及其他工具链，代码编辑器或IDE也是必不可少的。接下来，我们就来简单说说使用什么编辑器或IDE来开发Rust代码。</p>
<p>2023年Rust官方年度的用户调查显示，在编辑器/IDE使用排名中VSCode和VIM位列前二：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-6.png" alt="" /></p>
<p>Jetbrain推出的商业版<a href="https://www.jetbrains.com/rust/">RustRover</a>位居第三，正在迎头赶上，但由于是商业版，这里就不详细介绍了。下面我们分别介绍一下如何使用VSCode和VIM来开发Rust代码，都需要安装哪些插件。</p>
<h3>2.6.1 使用VSCode开发Rust</h3>
<p>使用上面介绍的rustup在本地安装Rust环境后，rust的相关工具(cargo、rustc、rustfmt、<a href="https://github.com/rust-lang/rust-analyzer">rust-analyzer</a>等)就都已经就绪！使用VSCode开发Rust只需再安装一个扩展插件即可，它就是由Rust官方维护的<a href="https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer">rust-analyzer</a>：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-7.png" alt="" /></p>
<p>该插件实现了Rust语言的Language Server Protocol，可以在开发者编写Rust代码时，提供代码补全、转到定义/实现/类型定义、查找所有引用、工作区符号搜索、符号重命名、悬停时的类型和文档、类型和参数名称的嵌入提示、语义语法高亮等功能。可以说，有了Rust-analyzer的帮助，开发者可以自由在Rust代码中徜徉了。</p>
<p>更详细的VSCode支持Rust开发的文档，可以参考<a href="https://code.visualstudio.com/docs/languages/rust">Rust in Visual Studio Code</a>。</p>
<h3>2.6.2 使用VIM开发Rust</h3>
<p>和VSCode仅需安装一个扩展插件相比，VIM的配置就相对复杂一些了。目前Rust+VIM的主流方案是<strong>rust.vim + coc.nvim + coc-rust-analyzer</strong>。</p>
<p>我们以安装了<a href="https://github.com/junegunn/vim-plug">vim-plug插件管理器</a>的VIM为例，下面是VIM的插件关系以及插件与Rust工具链的交互图：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher-rust-first-lesson-setup-dev-env-8.png" alt="" /></p>
<p>首先，通过vim-plug安装coc.nvim和rust.vim，我们需要在~/.vimrc中添加下面代码：</p>
<pre><code>call plug#begin()
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'rust-lang/rust.vim' "for rust
call plug#end()
</code></pre>
<p>然后在vim中执行:PlugInstall安装coc.nvim和rust.vim。</p>
<p>rust.vim是Rust团队官方维护的vim插件，用于提供Rust文件检测、语法高亮显示、代码格式化等，它需要Vim 8或更高版本才能实现完整功能。</p>
<p><a href="https://github.com/neoclide/coc.nvim">coc.nvim</a>则是一个强大的Neovim (Vim的衍生版本)插件，主要用于提供代码补全、语法检查、代码导航等功能，支持多种编程语言。它基于微软的 Language Server Protocol (LSP)，可以与各种语言服务器集成，从而为不同语言提供智能化的开发体验。</p>
<p>安装coc.nvim成功后，我们再在VIM中使用:CocInstall coc-rust-analyzer安装coc.nvim的插件：<a href="https://github.com/fannheyward/coc-rust-analyzer">coc-rust-analyzer</a>，通过该插件可以实现与LSP实现rust-analyzer的交互，从而实现代码补全、转到定义/实现/类型定义、查找所有引用等功能。</p>
<p>此外，我们还需要配置一下coc.nvim，配置文件在~/.vim/coc-settings.json中：</p>
<pre><code>{
    "languageserver" : {
            "rust": {
              "command": "rust-analyzer",
              "filetypes": ["rust"],
              "rootPatterns": ["Cargo.toml"]
            }
  }
}
</code></pre>
<p>安装好上述插件并完成配置后，你同样可以使用VIM在Rust代码中徜徉！</p>
<h2>2.7 小结</h2>
<p>在这一章里，我们学习了如何建立Rust开发环境。</p>
<p>首先我了解到，Rust有stable(稳定版)、beta(公测版)和nightly(每晚版)三种版本渠道，发布节奏是每6周一个新的稳定版，与Go语言有所区别。对于大多数开发者来说，选择最新的稳定版是最明智的选择。</p>
<p>接着，我介绍了在Linux环境下使用rustup这个官方工具安装Rust的方法。rustup提供了一键安装命令，可以方便地安装不同渠道的Rust版本。</p>
<p>安装完成后，rustup在主机的主目录下创建了.cargo和.rustup两个目录。.cargo/bin存放了cargo、rustc等命令行工具，.rustup/toolchains则存放了安装的Rust工具链。</p>
<p>我们还学会了如何使用rustup在不同版本间切换，并演练了如何安装指定版本的Rust。另外，通过rustup的”plus语法”，可以在单个命令中临时使用特定的Rust版本。当然Rust提供了不止一种方法，还有rust-toolchain.toml文件、环境变量等方法，请注意这些方法的优先级顺序。</p>
<p>最后，我们还介绍了如何利用Rust playground在线体验Rust编码，以及Rust编码使用的两种最常使用的IDE和编辑器：VSCode和VIM，针对这两个工具，我分别介绍了Rust开发环境的配置方法。</p>
<p>相信大家通过本章内容，已经可以成功搭建了Rust开发环境了，这为后续的Rust编程学习打下了坚实的基础。</p>
<hr />
<p><a href="https://public.zsxq.com/groups/51284458844544">Gopher部落知识星球</a>在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时，我们也会加强代码质量和最佳实践的分享，包括如何编写简洁、可读、可测试的Go代码。此外，我们还会加强星友之间的交流和互动。欢迎大家踊跃提问，分享心得，讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落，享受coding的快乐! 欢迎大家踊跃加入！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-tribe-zsxq-small-card.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/go-programming-from-beginner-to-master-qr.png" alt="img{512x368}" /></p>
<p><img src="http://image.tonybai.com/img/tonybai/go-first-course-banner.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/imooc-go-column-pgo-with-qr.jpg" alt="img{512x368}" /></p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻) &#8211; https://gopherdaily.tonybai.com</p>
<p>我的联系方式：</p>
<ul>
<li>微博(暂不可用)：https://weibo.com/bigwhite20xx</li>
<li>微博2：https://weibo.com/u/6484441286</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>Gopher Daily归档 &#8211; https://github.com/bigwhite/gopherdaily</li>
</ul>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2024, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2024/05/10/gopher-rust-first-lesson-setup-dev-env/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go 1.18中值得关注的几个变化</title>
		<link>https://tonybai.com/2022/04/20/some-changes-in-go-1-18/</link>
		<comments>https://tonybai.com/2022/04/20/some-changes-in-go-1-18/#comments</comments>
		<pubDate>Wed, 20 Apr 2022 15:10:18 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[amd64]]></category>
		<category><![CDATA[any]]></category>
		<category><![CDATA[append]]></category>
		<category><![CDATA[bytes]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[comparable]]></category>
		<category><![CDATA[Compiler]]></category>
		<category><![CDATA[constraints]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[Cut]]></category>
		<category><![CDATA[for-range]]></category>
		<category><![CDATA[fuzzing]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go-fuzz]]></category>
		<category><![CDATA[go-get]]></category>
		<category><![CDATA[go-module]]></category>
		<category><![CDATA[go.mod]]></category>
		<category><![CDATA[go.work]]></category>
		<category><![CDATA[Go1]]></category>
		<category><![CDATA[go1.18]]></category>
		<category><![CDATA[goget]]></category>
		<category><![CDATA[goimports]]></category>
		<category><![CDATA[goinstall]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[gopls]]></category>
		<category><![CDATA[govet]]></category>
		<category><![CDATA[Go工作区]]></category>
		<category><![CDATA[Inline]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[Mutex]]></category>
		<category><![CDATA[netip]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[pprof]]></category>
		<category><![CDATA[RobPike]]></category>
		<category><![CDATA[runtime]]></category>
		<category><![CDATA[SBOM]]></category>
		<category><![CDATA[Slice]]></category>
		<category><![CDATA[slices]]></category>
		<category><![CDATA[strings]]></category>
		<category><![CDATA[sync]]></category>
		<category><![CDATA[TLS]]></category>
		<category><![CDATA[TryLock]]></category>
		<category><![CDATA[typealias]]></category>
		<category><![CDATA[typeparameter]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vim-go]]></category>
		<category><![CDATA[切片]]></category>
		<category><![CDATA[方法集合]]></category>
		<category><![CDATA[泛型]]></category>
		<category><![CDATA[类型参数]]></category>
		<category><![CDATA[类型推导]]></category>
		<category><![CDATA[类型集合]]></category>
		<category><![CDATA[编译器]]></category>
		<category><![CDATA[自举]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=3506</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2022/04/20/some-changes-in-go-1-18 从3月23日开始，我居家办公了20+天。这期间我本来是应该有时间写下这篇综述类文章的，但是封了两天后，抢菜、带娃的事情就开始困扰着我。我实在没有下笔写下这篇文章的心思。4月13日终于解封了，上班后的气象就是不一样，人也精神了很多，于是这篇文章也被提上了日程。希望新冠疫情早日结束吧，希望每个人都能在晴朗的户外享受那春日的暖意。 2022年3月15日，Go团队在官方博客上官宣了Go 1.18正式版的发布。Go 1.18这个网红版本终于落地了。泛型的加入让Go 1.18成为继Go 1.0(首个正式版)、Go 1.5(实现自举、去C代码、新版GC)、Go 1.11(引入Go module)版本之后的又一里程碑版本。 泛型是Go语言开源以来最大的语法特性变化，其改动和影响都很大，Go核心团队尽管很努力了，但Go 1.18正式版本的发布时间还是延迟了一个月。不过好消息是加入泛型语法的Go 1.18继续保持了Go1兼容性，这本身就是Go团队的胜利，同样也是Go社区的幸运。 相较于之前的版本，Go 1.18版本改动很大，bug略多。好在发布一个月后，各种喧嚣都归于安静。笔者写稿时，Go 1.18.1已经发布，修正了许多问题，当然也包括一些与Go泛型有关的问题。 下面我们就来看看Go 1.18版本中值得关注的变化，我这里使用的版本为Go 1.18.1。 我们就先从泛型说起。 一. Go语法变化 1. 泛型：史上最复杂Go语法特性 以往Go发布大版本，Go语法变化一栏的内容总是寥寥无几，甚至是因没有变化而一笔带过。 更有甚者，从Go1.0到Go 1.17的语法变化屈指可数： Go 1.1版本：增加“method value”语法； Go 1.2版本：增加Full slice expression：a[low: high: max]； Go 1.4版本：新增for range x {&#8230;}形式的for-range语法； Go 1.5版本：支持省略map类型字面量（literal）中的key的类型； Go 1.9版本：新增了type alias语法； Go 1.13版本：增加以0b或0B开头的二进制数字字面量、以“0o”或“0O”开头的八进制数字字面量、以0x或0X开头是的十六进制形式的浮点数字面量以及支持在数字字面量中通过数字分隔符“_”提高可读性； Go 1.17版本：支持从切片到数组指针的转换。 我们看到，十年来，Go在纯语法层面的变化只有上面这么几个。而Go 1.18引入的泛型的复杂性足以超过上述版本的语法变化之和。面对新增加的泛型特性，即便是有着多年Go编程经验的Gopher，也会有一种“二次学艺”的感觉。这是因为Go泛型是Go诞生以来最复杂、最难读和理解的语法特性，当然泛型的复杂性不仅仅对Go语言生效，对其他具有泛型语法特性的编程语言来说，泛型也都是最复杂的语法。有志者可以去挑战一下C++的泛型：template。还有那本尤为烧脑的Andrei Alexandrescu [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/some-changes-in-go-1-18-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2022/04/20/some-changes-in-go-1-18">本文永久链接</a> &#8211; https://tonybai.com/2022/04/20/some-changes-in-go-1-18</p>
<blockquote>
<p>从3月23日开始，我居家办公了20+天。这期间我本来是应该有时间写下这篇综述类文章的，但是封了两天后，抢菜、带娃的事情就开始困扰着我。我实在没有下笔写下这篇文章的心思。4月13日终于解封了，上班后的气象就是不一样，人也精神了很多，于是这篇文章也被提上了日程。希望新冠疫情早日结束吧，希望每个人都能在晴朗的户外享受那春日的暖意。</p>
</blockquote>
<p>2022年3月15日，Go团队在官方博客上官宣了<a href="https://tonybai.com/2022/03/16/go-1-18-released">Go 1.18正式版的发布</a>。Go 1.18这个网红版本终于落地了。泛型的加入让Go 1.18成为继<a href="https://go.dev/blog/go1">Go 1.0(首个正式版)</a>、<a href="https://tonybai.com/2015/07/10/some-changes-in-go-1-5/">Go 1.5(实现自举、去C代码、新版GC)</a>、<a href="https://tonybai.com/2018/11/19/some-changes-in-go-1-11/">Go 1.11(引入Go module)</a>版本之后的又一<strong>里程碑版本</strong>。</p>
<p>泛型是Go语言开源以来<strong>最大的语法特性变化</strong>，其改动和影响都很大，Go核心团队尽管很努力了，但Go 1.18正式版本的发布时间还是延迟了一个月。不过好消息是加入泛型语法的Go 1.18继续保持了<a href="https://go.dev/doc/go1compat">Go1兼容性</a>，这本身就是Go团队的胜利，同样也是Go社区的幸运。</p>
<p>相较于之前的版本，Go 1.18版本改动很大，<a href="https://github.com/golang/go/milestone/254">bug略多</a>。好在发布一个月后，各种喧嚣都归于安静。笔者写稿时，<a href="https://groups.google.com/g/golang-announce/c/oecdBNLOml8">Go 1.18.1已经发布</a>，修正了许多问题，当然也包括一些与Go泛型有关的问题。</p>
<p>下面我们就来看看<strong>Go 1.18版本中值得关注的变化</strong>，我这里使用的版本为Go 1.18.1。</p>
<p>我们就先从泛型说起。</p>
<hr />
<h3>一. Go语法变化</h3>
<h4>1. 泛型：史上最复杂Go语法特性</h4>
<p>以往Go发布大版本，Go语法变化一栏的内容总是寥寥无几，甚至是因没有变化而一笔带过。</p>
<p>更有甚者，从Go1.0到Go 1.17的语法变化屈指可数：</p>
<ul>
<li>Go 1.1版本：增加<a href="https://go.dev/ref/spec#Method_values">“method value”语法</a>；</li>
<li>Go 1.2版本：增加<a href="https://go.dev/ref/spec#Slice_expressions">Full slice expression</a>：a[low: high: max]；</li>
<li><a href="https://tonybai.com/2014/11/04/some-changes-in-go-1-4/">Go 1.4版本</a>：新增for range x {&#8230;}形式的for-range语法；</li>
<li><a href="https://tonybai.com/2015/07/10/some-changes-in-go-1-5/">Go 1.5版本</a>：支持省略map类型字面量（literal）中的key的类型；</li>
<li><a href="https://tonybai.com/2017/07/14/some-changes-in-go-1-9/">Go 1.9版本</a>：新增了<a href="https://go.dev/ref/spec#Type_declarations">type alias语法</a>；</li>
<li><a href="https://tonybai.com/2019/10/27/some-changes-in-go-1-13/">Go 1.13版本</a>：增加以0b或0B开头的二进制数字字面量、以“0o”或“0O”开头的八进制数字字面量、以0x或0X开头是的十六进制形式的浮点数字面量以及支持在数字字面量中通过数字分隔符“_”提高可读性；</li>
<li><a href="https://tonybai.com/2021/08/17/some-changes-in-go-1-17">Go 1.17版本</a>：支持从切片到数组指针的转换。</li>
</ul>
<p>我们看到，十年来，Go在纯语法层面的变化只有上面这么几个。而Go 1.18引入的泛型的复杂性足以超过上述版本的语法变化之和。面对新增加的泛型特性，即便是有着多年Go编程经验的Gopher，也会有一种<strong>“二次学艺”</strong>的感觉。这是因为<strong>Go泛型是Go诞生以来最复杂、最难读和理解的语法特性</strong>，当然泛型的复杂性不仅仅对Go语言生效，对其他具有泛型语法特性的编程语言来说，泛型也都是最复杂的语法。有志者可以去挑战一下C++的泛型：template。还有那本尤为烧脑的Andrei Alexandrescu 的<a href="https://book.douban.com/subject/1119904/">《C++设计新思维: 泛型编程与设计模式之应用》</a>，英文书名是<a href="https://book.douban.com/subject/1755195/">《Modern C++ Design: Generic Programming and Design Patterns Applied》</a>。</p>
<p><img src="https://tonybai.com/wp-content/uploads/some-changes-in-go-1-18-2.jpg" alt="" /></p>
<p>同样也是因为泛型的复杂性，Go团队在<a href="https://go.dev/doc/go1.18">Go 1.18的发布说明文档</a>中保留了在将来的版本中因修复Go泛型bug而对Go 1.18版本编译的程序带来破坏的权力。当然Go团队也承诺将尽可能地减少任何此类破坏，但不能保证此类破坏为零。</p>
<p>另外，Go 1.18的泛型实现并非完全版，有很多使用上的约束。这些约束很大可能将在后续的Go版本中逐步取消掉。并且Go 1.18中的实现与<a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md">Type Parameter Proposal的design文档</a>有一定差异，Go官方建议以<a href="https://go.dev/ref/spec">Go语言的规范</a>为准。</p>
<h4>2. 泛型的主要语法点</h4>
<p>前面也说了，Go泛型是Go开源以来在语法层面最大的一次变动，Go泛型的最后一版技术提案长达数十页，我们要是把其中的细节都展开细讲，那都可以自成一本小册子了。在这篇综述类文章中，我仅对Go泛型的主要语法点做简要说明。在日后文章中，我们再深入到泛型的语法细节，做逐一细致剖析。</p>
<p>关于Go泛型的主要语法点，其实在Go官博的<a href="https://tonybai.com/2022/03/25/intro-generics">“Go泛型介绍”</a>中都有提及：</p>
<p>泛型在Go语言中增加了三个新的重要内容：</p>
<ul>
<li>函数和类型新增对<strong>类型形参(type parameters)</strong>的支持。</li>
<li>将接口类型定义为类型集合，包括没有方法的接口类型。</li>
<li>支持类型推导，大多数情况下，调用泛型函数时可省略类型实参(type arguments)。</li>
</ul>
<p>下面我们分别来看看。</p>
<h5>类型形参(type parameter)</h5>
<p>类型形参是在函数声明、方法声明的receiver部分或类型定义的类型参数列表中，声明的（非限定）类型名称。类型参数在声明中充当了一个未知类型的占位符（placeholder），在泛型函数或泛型类型实例化时，类型形参会被一个类型实参(type argument)替换。</p>
<p>为了让你更好地理解类型参数究竟如何声明，它又起到了什么作用，我们以函数为例，对普通函数的参数与泛型函数的类型参数作一下对比：</p>
<p>我们知道，普通函数的参数列表是这样的：</p>
<pre><code>func Foo(x, y aType, z anotherType)
</code></pre>
<p>这里，x, y, z是形参（parameter）的名字，也就是变量，而aType，anotherType是形参的类型，也就是类型。</p>
<p>我们再来看一下泛型函数的类型参数（type parameter）列表：</p>
<pre><code>func GenericFoo[P aConstraint, Q anotherConstraint](x,y P, z Q)
</code></pre>
<p>这里，P，Q是类型形参的名字，也就是类型，aConstraint，anotherConstraint代表类型参数的约束（constraint），我们可以理解为对类型参数可选值的一种限定。</p>
<p>在类型参数列表中修饰类型参数的就是约束（constraint）。那什么是约束呢？我们继续往下看。</p>
<h5>约束（constraint）</h5>
<p>约束（constraint）规定了一个类型实参（type argument）必须满足的条件要求。如果某个类型满足了某个约束规定的所有条件要求，那么它就是这个约束修饰的类型形参的一个合法的类型实参。</p>
<p>在Go泛型中，我们<strong>使用interface类型来定义约束</strong>。为此，Go接口类型的定义也进行了扩展，我们既可以声明接口的方法集合，也可以声明可用作类型实参的类型列表。</p>
<p>下面是一个约束定义与使用的示例：</p>
<pre><code>type C1 interface {
    ~int | ~int32
    M1()
}

type T struct{}
func (T) M1() {
}

type T1 int
func (T1) M1() {
}

func foo[P C1](t P)() {
}

func main() {
    var t1 T1
    foo(t1)
    var t T
    foo(t) // 编译器报错：T does not implement C1
}
</code></pre>
<p>在这段代码中，C1是我们定义的约束，它声明了一个方法M1，以及两个可用作类型实参的类型(~int | ~int32)。我们看到，类型列表中的多个类型实参类型用“|”分隔。</p>
<p>在这段代码中，我们还定义了两个自定义类型T和T1，两个类型都实现了M1方法，但T类型的底层类型为struct{}，而T1类型的底层类型为int，这样就导致了虽然T类型满足了约束C1的方法集合，但类型T因为底层类型并不是int或int32而不满足约束C1，这也就会导致foo(t)调用在编译阶段报错。不过，我这里还要建议你：做约束的接口类型与做传统接口的接口类型最好要分开定义，除非约束类型真的既需要方法集合，也需要类型列表。</p>
<p>为了让大家更好理解这种对接口类型的扩展，Go引入了类型集合(type set)来解释这一切。<a href="https://tonybai.com/2022/03/25/intro-generics">“Go泛型介绍”</a>中有对type set的图解，这里就不赘述了，大家可以点击链接移步阅读。</p>
<h5>类型具化(instantiation)与类型推导(type inference)</h5>
<p>像上面例子中main函数对foo(t1)的调用就利用到了类型具化和类型推导两个特性。</p>
<p>foo是一个泛型函数，它的函数声明中带有一个由C1约束的类型形参P，而用类型实参T1初始化P的过程就是类型具化。不过大家也注意到了，我们没有使用：foo&#91;T1&#93;(t1)，而是省略了显式对P进行初始化，直接使用了foo(t1)，这就是Go类型推导带来的便利。Go编译器会根据传入的实参的类型，进行类型实参(type argument)的自动推导。自动类型推导使得人们在编写调用泛型函数的代码时可以使用一种更为自然的风格。</p>
<h5>泛型类型(generic type)</h5>
<p>除了函数可以携带类型参数变身为“泛型函数”外，类型也可以拥有类型形参而化身为“泛型类型”，比如下面代码就定义了一个向量泛型类型：</p>
<pre><code>type Vector[T any] []T
</code></pre>
<p>这是一个带有类型参数的类型定义，类型参数位于类型名的后面，同样用方括号括起。在类型定义体中可以引用类型参数列表中的参数名（比如T）。类型参数同样拥有自己的约束，如上面代码中的any。</p>
<p>在Go 1.18中，any是interface{}的别名，也是一个预定义标识符，使用any作为类型参数的约束，代表没有任何约束。关于如何使用any以及使用any的注意事项，请移步到我之前的文章<a href="https://tonybai.com/2021/12/18/replace-empty-interface-with-any-first-after-switching-to-go-1-18">《切换到Go 1.18后的第一件事：将interface{}全部替换为any》</a>。</p>
<p>下面是另一个泛型类型的定义：</p>
<pre><code>type Tree[T interface{}] struct {
    left, right *Tree[T]
    value       T
}

func (t *Tree[T]) Lookup(x T) *Tree[T] { ... }

var stringTree Tree[string]
</code></pre>
<p>在上面这个例子中，泛型类型Tree存储了类型参数T的值。泛型类型也可以有方法，比如本例中的Lookup。为了使用一个泛型类型，它必须被实例化，比如：Tree[string]是一个用类型实参string来实例化Tree的例子。</p>
<h5>当前泛型实现的不足</h5>
<p>泛型对Go项目的影响是方方面面的，在一个版本迭代周期内将泛型的全部特性都实现的确难了一些。因此，Go 1.18当前的Go泛型实现尚不完整，尚有限制，根据Go 1.18的发布说明文档，限制包括下面几点：</p>
<ul>
<li>Go编译器不能处理泛型函数或方法中的类型声明，Go团队希望在未来的版本中提供对该功能的支持。</li>
</ul>
<pre><code>func GenericsFoo[T any](s T) T {
    type bar int // type declarations inside generic functions are not currently supported
    var a bar
    println(a)
    return s
}
</code></pre>
<ul>
<li>Go编译器不支持预定义的函数real、imag和complex处理泛型类型实参。Go团队希望在未来的版本中取消这一限制。</li>
</ul>
<pre><code>package main

import (
    "golang.org/x/exp/constraints"
)

func GenericsFoo[T constraints.Complex](s T) T {
    n := real(s) // s (variable of type T constrained by constraints.Complex) not supported as argument to real for go1.18 (see issue #50937
    println(n)

    i := complex(s, s) // invalid argument: arguments have type T, expected floating-point
    _ = i
    return s
}

func main() {
    var i = complex(1.0, 2.0) // 1+2i
    GenericsFoo(i)
}
</code></pre>
<ul>
<li>Go编译器只支持在参数类型为P的值x上调用方法m，前提是：m必须是由P的约束接口显式声明的。同样地，method valuex.m和method expression P.m也只有在P明确声明了m的情况下才会被支持。即使P类型集合中的所有类型都实现了m，但如果没有显示声明m，那么也不支持在x上调用m。Go团队希望在未来的版本中删除这一限制。</li>
</ul>
<pre><code>package main

type C interface {
    T | T1 // T和T1都实现了M1方法
}

func GenericsFoo[P C](p P) {
    p.M1() // p.M1 undefined (type P has no field or method M1)
}

type T struct{}

func (T) M1() {}

type T1 struct{}

func (T1) M1() {}

func main() {
    GenericsFoo(T{})
}

</code></pre>
<ul>
<li>Go编译器目前不支持访问一个结构字段x.f，其中x是类型参数类型，即使类型参数的类型集合中的所有类型都有一个字段f。Go团队可能会在未来的版本中取消这一限制。</li>
</ul>
<pre><code>package main

type C interface {
    T | T1 // T和T1的类型定义中都包含名为Name的字段
}

func GenericsFoo[P C](p P) {
    _ = p.Name // p.Name undefined (type P has no field or method Name)
}

type T struct {
    Name string
}

type T1 struct {
    Name string
}

func main() {
    GenericsFoo(T{})
}
</code></pre>
<ul>
<li>目前Go编译器不允许将类型参数或指向类型参数的指针作为结构体类型嵌入字段(未命名字段)。同样，也不允许在一个接口类型中嵌入一个类型参数。目前Go团队还不确定这些限制在未来版本是否会被放开。                </li>
</ul>
<pre><code>package main

type F[T any, P any] struct {
    Name string
    *T //embedded field type cannot be a (pointer to a) type parameter
    P // embedded field type cannot be a (pointer to a) type parameter
}

type MyInterface interface{}

type GenericsInterface[I MyInterface] interface {
    M1()
    I // cannot embed a type parameter
}

func main() {
    var f F[string, string]
    _ = f
}
</code></pre>
<ul>
<li>Go编译器不支持在包含1个以上类型元素的union类型定义中包含一个具有非空方法集的接口类型。这是否会在未来版本中被允许，Go团队目前还不确定。</li>
</ul>
<pre><code>package main

type MyInterface interface {
    M1()
}

type GenericsInterface interface {
    ~int | MyInterface | float64 // cannot use main.MyInterface in union (main.MyInterface contains methods)
}

func main() {
}
</code></pre>
<p>另外一个大家广为关注的是，普通类型的方法声明中不支持类型参数：</p>
<pre><code>package main

type F struct{}

func (F) M1[T any](t T){} // syntax error: method must have no type parameters

func main() {
    var f F[string]
    f.M1("hello")
}
</code></pre>
<p>不过这不是实现层面的限制，而是Go泛型技术草案就是这么定的。至于后续是否能支持在方法中使用类型参数还不确定。不过上述问题可以通过带有类型参数的泛型类型来“缓解”。</p>
<p>泛型类型可以有自己的方法，在泛型类型的方法声明中receiver中使用与类型声明相同的类型参数，这个类型参数也可以在方法的普通参数列表中使用，如下面例子：</p>
<pre><code>package main

type F[T any] struct{}

func (F[T]) M1(t T) {} // ok

func main() {
    var f F[string]
    f.M1("hello")
}
</code></pre>
<h5>官方维护的泛型包</h5>
<p>Go 1.18可以说仅提供了一个Go泛型的最小版本，除了语法，外加两个预定义类型：comparable和any。原本想在标准库中加入的constraints、slices和maps泛型包，因Go老父亲<a href="https://github.com/golang/go/issues/48918">Rob Pike的一条comment</a>而被暂时搁置了。Rob Pike的理由很简单，<a href="https://tonybai.com/2021/04/07/go-generics-use-type-sets-to-remove-type-keyword/">Go泛型</a>是Go诞生以来最大的一次语言变化，Go 1.18版本承载了太多的change，容易出错。并且Go核心开发团队也没有使用新泛型的经验，他建议Go核心开发团队应该多等待、观察和学习，不要把步子迈得太大，<a href="https://tonybai.com/2021/10/28/expectations-for-generics-in-go-1.18">Go应该按照自己的节奏稳步前进</a>。</p>
<p>于是前面提到的三个包被放在了golang.org/x/exp下面了：</p>
<pre><code>golang.org/x/exp/constraints
golang.org/x/exp/slices
golang.org/x/exp/maps
</code></pre>
<p>待时机成熟，这些包会像当年http2包一样进入到Go标准库中。</p>
<h5>Go工具链对泛型语法的支持情况</h5>
<p>Go泛型出炉后，Go官方维护的Go工具链上的工具都基本确定了支持泛型语法的计划。到Go 1.18发布时，gofmt/goimports、go vet、gopls(从v0.8.1版本开始支持)都实现了对泛型的支持。</p>
<p>不过这里除了gofmt是与Go安装包一起发布的，其他工具都需要自己安装和升级到最新版本。否则一旦使用到泛型语法或新增的像any、comparable等预定义标识符，你的编辑器就会给出各种错误提示。</p>
<p>如果你和我一样使用<a href="https://tonybai.com/2016/09/08/upgrade-vim-go/">vim+vim-go+goimports+gopls</a>，那么要想编辑器支持go 1.18，可使用下面命令升级工具版本来支持go 1.18的泛型：</p>
<pre><code>$go install golang.org/x/tools/cmd/goimports@latest
$go install golang.org/x/tools/gopls@latest
</code></pre>
<p>当然Go社区还有很多工具尚未及时赶上步伐，这个要给Go社区一定的时间。</p>
<p>关于Go泛型语法的细节以及实现原理，我会逐渐在后续文章中进行专门讲解。</p>
<p>讲完泛型这个大部头儿后，接下来，我们再来看看Go编译器与Go module的变化。</p>
<h3>二. Go编译器与Go module变化</h3>
<h4>1. 修正的语法bug</h4>
<p>我们知道在Go函数内声明变量后，如果未使用，Go编译器会报错。但Go 1.18版本之前，<a href="https://github.com/golang/go/issues/49214">Go编译器对于下面例子中的变量p是不会报错的</a>，即便在main中没有使用。</p>
<p>Go 1.18修正了这个问题，如果用Go 1.18编译该例子，会出现注释中的编译器错误。</p>
<pre><code>package main

func main() {
    p := true // go 1.18会报错：p declared but not used，但Go 1.18之前的版本不会。
    func() {
        p = true
    }()
}
</code></pre>
<p>同时，gopls和go vet也都会针对上述问题给出错误提示。</p>
<h4>2. 在AMD64平台上引入architectural level</h4>
<p>众所周知，Go语言在目标代码的优化上还有很大的提升空间。在Go 1.18版本中，Go引入一个算是优化的措施，即<a href="https://github.com/golang/go/wiki/MinimumRequirements#amd64">在AMD64平台上引入architectural level的概念</a>。level越高，可用指令越新，编译出的使用新指令的代码的性能可能有一定提升。</p>
<p>Go 1.18通过GOAMD64这个环境变量来指示编译器采用的level，默认使用v1版本。这个版本在生产的代码中使用了所有x86-64 cpu都支持的指令。说白了，就是使用最基本的指令，兼容性好，但性能也是最差的。</p>
<p>GOAMD64环境变量的另外三个候选值为v2、v3、v4。版本越高，兼容性越差，但性能可能因使用新指令而得到提升。</p>
<ul>
<li>GOAMD64=v2: 所有v1版指令, 外加CMPXCHG16B, LAHF, SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3；</li>
<li>GOAMD64=v3: 所有v2版指令, 外加AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, OSXSAVE；</li>
<li>GOAMD64=v4: 所有v3版指令, 外加AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL。</li>
</ul>
<p>在优化的道路，Go团队一直在努力，这不Go编译器现在还可以inline带有range循环或带有label的循环语句的函数了。</p>
<h4>3. 丰富了SBOM信息</h4>
<p>这些年来，关于软件供应链的安全问题频发，软件供应链已然成为IT安全领域的一个热点。Go作为云原生平台、中间件以及服务的头部开发语言，其自身安全性以及构建出的软件的安全性就变得至关重要了。Go在安全方面的投入也是逐渐增大，手段也在逐渐增多与丰富。SBOM(软件物料清单)作为缓解软件供应链攻击的重要防护手段，Go在1.13版本就提供了相关支持，在Go 1.18版本中，Go更是丰富了提供的SBOM信息，这方面的详情可参见之前的文章：<a href="https://tonybai.com/2022/03/14/software-supply-chain-security-in-go">《聊聊Go语言的软件供应链安全》</a>。</p>
<h4>4. Go泛型给compiler带来的负面影响</h4>
<p>Go泛型的引入增加了Go语言的表达力，但也对Go编译器带来了不小的负面影响，其中最大的影响就是编译速度。从Go 1.18发布说明文档来看，Go 1.18的编译速度要比Go 1.17版本下降15%，并且即便你在代码中完全没有使用泛型语法，这个性能下降也是有的。所以<a href="https://github.com/golang/go/issues/49569">这也是Go团队在Go 1.19中要重点解决的问题</a>。</p>
<h4>5. go module变化</h4>
<p>从<a href="https://tonybai.com/2021/02/25/some-changes-in-go-1-16">Go 1.16版本</a>开始，Go module已进入成熟期。不过依然有一些小问题需要修复，其中一个就是go.mod和go.sum究竟哪个命令有权修改。Go 1.18明确了能修改go.mod, go.sum的命令只有三个：go get, go mod tidy和go mod download。这样开发人员就可以放心的在项目根目录下执行go工具链提供的其他命令了。</p>
<h4>6. 引入Go workspace(工作区)</h4>
<p>Go module的引入大大改善了Go包依赖与构建问题。但目前Go module在软件协作开发过程中仍存在导致体验差的两个问题，并且这两个问题在原有go module机制下面很难得到根本解决。这两个问题是：</p>
<ul>
<li>对依赖包进行自行修改，并基于本地修改后的依赖包进行构建；</li>
<li>依赖本地尚未发布的module。</li>
</ul>
<p>原有的go module replace机制在协作的情况下，体验较差，给开发人员带去一定额外的心智负担。于是Go开发者Michael Matloob在2021年4月提出的一个<a href="https://github.com/golang/proposal/blob/master/design/45713-workspace.md">名为“Multi-Module Workspaces in cmd/go”的proposal</a>。这个proposal引入一个go.work文件用于开启Go工作区模式。go.work通过use指示符设置一些本地路径，这些路径下的go module构成一个工作区(workspace)，<strong>Go命令可以操作这些路径下的go module，也会优先使用工作区中的go module</strong>。同时，go.work是本地环境相关的，无需提交到代码仓库中，每个开发者可以根据自己的开发环境设置拥有仅属于自己的go.work文件。</p>
<p>关于Go工作区机制，我在<a href="https://tonybai.com/2021/11/12/go-workspace-mode-in-go-1-18">《Go 1.18新特性前瞻：Go工作区模式》</a>一文中有详细介绍，大家可以移步到那篇文章认真阅读。不过那篇文章是在Go 1.18 beta1版发布之前写的，当时的一些go.work的内容，比如像directory指示符在Go 1.18正式版中已经发生了变化，这个大家要注意一下。</p>
<p>看完编译器，我们再来简单说说其他工具链。</p>
<h3>三. Go工具链变化</h3>
<h4>1. go fuzzing</h4>
<p>Go工具链侧最大的变化莫过于引入对fuzzing的原生支持。Fuzzing，又叫fuzz testing，中文叫做模糊测试或随机测试。其本质上是一种自动化测试技术，更具体一点，它是一种基于随机输入的自动化测试技术，常被用于发现处理用户输入的代码中存在的bug和问题。</p>
<p>在具体实现上，Fuzzing不需要像单元测试那样使用预先定义好的数据集作为程序输入，而是会通过数据构造引擎自行构造或基于开发人员提供的初始数据构造一些随机数据，并作为输入提供给我们的程序，然后监测程序是否出现panic、断言失败、无限循环等。这些构造出来的随机数据被称为<strong>语料(corpus)</strong>。另外Fuzz testing不是一次性执行的测试，如果不限制执行次数和执行时间，Fuzz testing会一直执行下去，因此它也是一种持续测试的技术。</p>
<p>Go 1.18将fuzz testing纳入了go test工具链，与单元测试、性能基准测试(https://www.imooc.com/read/87/article/2439)等一起成为了Go原生测试工具链中的重要成员。</p>
<p>go fuzzing test的测试用例与普通的测试用例(TestXxx)、性能基准测试(BenchmarkXxx)等一样放在xx_test.go中，只不过用例对应的函数名样式换为了FuzzXxx了。一个简单的Fuzzing test用例如下：</p>
<pre><code>func FuzzXxx(f *testing.F) {
    // 设置种子语料(可选)

    // 执行Fuzzing
    f.Fuzz(func(t *testing.T, b []byte) {
        //... ...
    })
}
</code></pre>
<p>关于Go Fuzzing test，我在<a href="https://tonybai.com/2021/12/01/first-class-fuzzing-in-go-1-18">《Go 1.18新特性前瞻：原生支持Fuzzing测试》</a> 有十分全面系统的说明，大家可以移步到那篇文章阅读了解。</p>
<p>这里需要大家额外注意的是，Fuzzing测试虽然写法上与单元测试、benchmark test很像，也很简单，但Fuzzing测试是持续运行的，不会停下来的，因此就像Go 1.18版本说明中提示的那样：Fuzzing测试会消耗大量的内存，在运行时可能会影响你的机器性能。还要注意的是，在运行时，模糊引擎会将扩大测试范围的数值写入\$GOCACHE/fuzz内的模糊缓存目录。目前对写入模糊缓存的文件数量或总字节数没有限制，所以它可能会占用大量的存储空间（可能是几个GB甚至更多）。因此建议找一台专门的高配机器来跑fuzzing test。</p>
<h4>2. go get</h4>
<p>在Go module构建模式下，go get回归本职工作，专注于获取go module以及对应的依赖module。不再执行编译和安装工作。这样一来，原本被go get剥夺了光环的go install在module-aware模式下重新拿回本属于自己的职能：安装指定版本或latest版本的module和可执行文件。</p>
<p>最后，我们再来看看其他的一些小变化。</p>
<h3>四. 其他的minor变化</h3>
<h4>1. gofmt支持并发</h4>
<p>“gofmt的代码风格不是某个人的最爱，而是所有人的最爱”。gofmt代码风格已经成为Go开发者的一种共识，融入到Go语言的开发文化当中了。Go 1.18为Go开发人员带来了支持并发的gofmt，毫无疑问，其最大的好处就是快，尤其是在多核cpu上，gofmt可以利用更多的算力快速完成代码风格的格式化。</p>
<h4>2. 内置函数append对切片的扩容算法发生变化</h4>
<p>我们都知道append操作切片时，一旦切片已满(len==cap)，append就会重新分配一块更大的底层数组，然后将当前切片元素copy到新底层数组中。通常在size较小的情况下，append都会按2倍cap扩容，size大的情况，比如已经是1024了，那么Go 1.17不会double分配。Go 1.18中的算法有一定变化，目的是使得在一个门槛值前后的变化更丝滑。具体算法大家看下面\$GOROOT/src/runtime/slice.go中的growslice函数中的部分逻辑：</p>
<pre><code>func growslice(et *_type, old slice, cap int) slice {
    ... ...

    newcap := old.cap
    doublecap := newcap + newcap
    if cap &gt; doublecap {
        newcap = cap
    } else {
        const threshold = 256
        if old.cap &lt; threshold {
            newcap = doublecap
        } else {
            // Check 0 &lt; newcap to detect overflow
            // and prevent an infinite loop.
            for 0 &lt; newcap &amp;&amp; newcap &lt; cap {
                // Transition from growing 2x for small slices
                // to growing 1.25x for large slices. This formula
                // gives a smooth-ish transition between the two.
                newcap += (newcap + 3*threshold) / 4
            }
            // Set newcap to the requested cap when
            // the newcap calculation overflowed.
            if newcap &lt;= 0 {
                newcap = cap
            }
        }
    }
    ... ...
}
</code></pre>
<p>另外从代码来看，和Go 1.17以1024作为大小分界不同，Go 1.18使用256作为threshold。这个大家要注意。</p>
<h4>3. 新增net/netip包</h4>
<p>Go 1.18标准库在net下面新增加了netip包。这源于原Go核心开发者<a href="https://github.com/bradfitz">Brad Fitzpatrick</a>在其<a href="https://tailscale.com/blog/netaddr-new-ip-type-for-go/">创业项目tailscale中遇到的问题</a>。Brad发现标准库中现有的表示IP相关信息的net.IP有如下这么多不足：</p>
<p><img src="https://tonybai.com/wp-content/uploads/some-changes-in-go-1-18-3.png" alt="" /></p>
<p>于是<a href="https://github.com/golang/go/issues/46518">Brad提议新增一个占用较少的内存、不可变的并且是可比较的、可作为map key的IP的新表示</a>，这就是netip.Addr以及围绕netip.Addr的一系列类型与方法。</p>
<p>关于netip包的内容还不少，大家可以查看<a href="https://pkg.go.dev/net/netip">netip包的ref</a>来详细了解这个包。</p>
<h4>4. 两个重要的安全变化</h4>
<p>安全问题日益严重，Go标准库也在紧跟安全趋势的步伐。</p>
<p>在Go 1.18中，tls client默认将使用TLS 1.2版本。当然如果你要显式将Config.MinVersion设置为VersionTLS10，TLS 1.0和1.1依然可以使用。</p>
<p>此外，Go 1.18中crypto/x509包默认将拒绝使用SHA-1哈希函数签名的证书(自签发的除外)。通过GODEBUG=x509sha1=1可以临时支持SHA-1，但从Go 1.19版本开始，SHA-1将被永久踢出。</p>
<h4>5. strings包和bytes包新增Cut函数</h4>
<p>strings包和bytes包都增加了实用函数Cut(注：strings和bytes包保持API一致性的传统由来已久)。以字符串为例，Cut函数的语义就是将一个输入字符串中的某一段字符串“切掉”。Cut函数的原型如下：</p>
<pre><code>func Cut(s, sep string) (before, after string, found bool)
</code></pre>
<p>如果没找到要切掉的部分，则最后的返回值为false，before为原字符串s，而after则为”"。</p>
<pre><code>var s = "hello, golang"

b, a, f := strings.Cut(s, "java")
fmt.Printf("before=%s, after=%s, found=%t\n", b, a, f) // before=hello, golang, after=, found=false
</code></pre>
<p>如果找到了要切掉的部分，则最后的返回值为true，before为“被切掉部分”的前面的字符串，after则为“被切掉部分”的后面的字符串。</p>
<pre><code>b, a, f = strings.Cut(s, "lang")
fmt.Printf("before=%s, after=%s, found=%t\n", b, a, f) // before=hello, go, after=, found=true
</code></pre>
<p>如果输入字符串中有多个与要切掉的部分匹配的字串，Cut函数只会切掉第一个匹配的字串。</p>
<pre><code>b, a, f = strings.Cut(s, "o")
fmt.Printf("before=%s, after=%s, found=%t\n", b, a, f) // before=hell, after=, golang, found=true
</code></pre>
<h4>6. runtime/pprof精确性提升</h4>
<p>Go 1.18 runtime/pprof在Linux上采用每线程定时器来驱动采样，目的就是提升在高负荷下采样数据的精确性，减少<a href="https://github.com/golang/go/issues/35057">数据丢失或不准的情况</a>。</p>
<h4>7. sync包新增Mutex.TryLock, RWMutex.TryLock和RWMutex.TryRLock</h4>
<p>Go团队在社区的强烈要求下，还是在sync包中加上了Mutex.TryLock, RWMutex.TryLock和RWMutex.TryRLock。但说实话，我个人尚未遇到非要使用TryLock的场景。Go团队在TryLock方法的注释中也给出了使用提示：<strong>请注意，虽然TryLock的正确使用确实存在，但它们是罕见的，而且使用TryLock的使用往往是mutex在特定使用中更深层次问题的标志</strong>。</p>
<p>尽量不要用就完了！</p>
<h3>五. 小结</h3>
<p>从上面内容来看，Go 1.18还真是一个大改动的版本。很多变化都值得后续细致学习和探索。Go 1.18由于引入泛型，我个人还是建议暂缓将其用于生产环境。就像go module引入后，经历go 1.11~go 1.16才逐渐成熟，Go泛型的成熟想必也要至少2-3个版本。在这个阶段，先把精力放在对泛型的学习上以及如何利用泛型改善我们的代码上，但也要注意：泛型大幅提高了代码的复杂性，使用泛型的代码在可读性方面必然有下降，大家不要滥用泛型，更不要显然像c++ template使用的那种奇技淫巧中去。那就与<a href="https://time.geekbang.org/column/article/426740">Go语言的设计哲学</a>背道而驰了。</p>
<hr />
<p><a href="https://wx.zsxq.com/dweb2/index/group/51284458844544">“Gopher部落”知识星球</a>旨在打造一个精品Go学习和进阶社群！高品质首发Go技术文章，“三天”首发阅读权，每年两期Go语言发展现状分析，每天提前1小时阅读到新鲜的Gopher日报，网课、技术专栏、图书内容前瞻，六小时内必答保证等满足你关于Go语言生态的所有需求！2022年，Gopher部落全面改版，将持续分享Go语言与Go应用领域的知识、技巧与实践，并增加诸多互动形式。欢迎大家加入！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-tribe-zsxq-small-card.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/go-programming-from-beginner-to-master-qr.png" alt="img{512x368}" /></p>
<p><img src="http://image.tonybai.com/img/tonybai/go-first-course-banner.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/imooc-go-column-pgo-with-qr.jpg" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/imooc-k8s-practice-with-qr.jpg" alt="img{512x368}" /></p>
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/。smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。2020年4月8日，中国三大电信运营商联合发布《5G消息白皮书》，51短信平台也会全新升级到“51商用消息平台”，全面支持5G RCS消息。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻)归档仓库 &#8211; https://github.com/bigwhite/gopherdaily</p>
<p>我的联系方式：</p>
<ul>
<li>微博：https://weibo.com/bigwhite20xx</li>
<li>微信公众号：iamtonybai</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>“Gopher部落”知识星球：https://public.zsxq.com/groups/51284458844544</li>
</ul>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2022, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2022/04/20/some-changes-in-go-1-18/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hugo作者、Go核心开发团队成员谈诞生13年的Go语言：生态系统、演化与未来[译]</title>
		<link>https://tonybai.com/2021/01/02/go-language-13-years/</link>
		<comments>https://tonybai.com/2021/01/02/go-language-13-years/#comments</comments>
		<pubDate>Sat, 02 Jan 2021 04:09:50 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[Dart]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[Flutter]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go-module]]></category>
		<category><![CDATA[go1.11]]></category>
		<category><![CDATA[gohugo]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[hugo]]></category>
		<category><![CDATA[InfluxDB]]></category>
		<category><![CDATA[infoq]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Module]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pkg.go.dev]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[syncthing]]></category>
		<category><![CDATA[terraform]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vitess]]></category>
		<category><![CDATA[专栏]]></category>
		<category><![CDATA[垃圾回收]]></category>
		<category><![CDATA[泛型]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=3064</guid>
		<description><![CDATA[本文翻译自《Go Language at 13 Years: Ecosystem, Evolution, and Future in Conversation with Steve Francia》。 译注：Go开源于2009年，如果从那时算起，Go才11岁；但在Go核心开发团队眼中，Go的真正诞生年份是2007年，至今13个年头了。关于Go的演化简史可以参见我的专栏文章：《Go语言的前生今世》。 本文要点： Go的简单性让你可以快速上手使用它&#8211;你可以在一个下午就消化掉整个Go语言规范； 作者认为Go是当今最好的现代语言之一（其他的还包括：Dart、Flutter和Rust）； Go的未来是由它的开源社区决定的，它对所有的功能建议进行讨论和辩论。除非达成明确的共识，否则该功能不会被实现。 社区的规模大约每18个月翻一番。 最初，Go的早期采用者多来自python或ruby等动态语言的开发人员，现在随着语言的成熟，来自Java、.NET和C++程序员也开始接纳并使用Go。 在充满挑战的一年里，社区适应了相互支持，出现了多个meetup，并出现了新的资源。 编程语言的历史只朝着一个方向发展，每一种新的语言的出现都让事情都变得越来越复杂，越来越抽象。然而，就在十几年前，Go在Google诞生了。这种编程语言走的是另外一条路，它把赌注押在了简单和精心的设计和实现上。这个配方一直保留到今天，你可以直接开始写Go代码，没有太大的障碍。当你想到现代软件的大部分流行和可靠的作品都是用Go编写的，比如Docker、Kubernetes、Prometheus等，这就足以让你印象深刻。这个列表还在持续增加。为了了解Go从哪里来，更重要的是它要往哪里去，InfoQ联系了Google负责战略和产品的Go编程语言团队核心成员Steve Francia(译注：他也是知名静态站点生成工具gohugo的作者)。 InfoQ：非常感谢您抽出宝贵时间回答读者的几个问题。我们能否首先请您介绍一下自己并描述您在Google的角色和日常工作？ Steve Francia：我是Steve Francia，是Google Go编程语言团队的核心成员，负责产品和策略。 InfoQ：您将技术挑战和工程挑战归因于十三年前点燃了Go的火花。还有其他吗？当时Google的官方编程语言是什么，缺少什么？ Francia：创建Go的主要动机是认识到我们的系统已经变得越来越复杂。为了跟上“Google规模”的指数增长，我们设计了复杂的系统来满足我们的需求。随着时间的流逝，我们又在这些基础系统/库和语言的基础上构建了新的复杂系统。人们通常不会想到复杂性的隐性成本。事实是，代码被读取的次数比其编写的次数多。复杂性给团队效率带来了极大的负担。相反，Go很简单。你仅需要花一个下午的时间来学习。Go代码非常简单易读。这种简单性使团队能够以前所未有的方式进行协作。 InfoQ：这一切是如何开始的？是自上而下的请求（管理人员要求一种语言来满足需求），还是自下而上的请求？来自Google的20％著名的创新？工程师尽其所能-解决问题？ Francia：没人要求过。这实际上不是一个20％的项目。是一次谈话导致一个研究项目获得了关注，并且被广泛采用，超出了所有人的想象。当然，Google从上到下都对寻找降低复杂性和提高生产力的方法感兴趣。 InfoQ：在起步阶段，有一种说法是，如果您在发布之日不为自己的产品感到羞耻，那么您可能为时已晚。Go于2011年发布1.0版本，当时Google为了支持它，将其添加到Google App Engine中，YouTube也开始使用Vitess(译注：一种Go实现的Mysql前置代理，用于建立mysql集群）。Go在发布时就已经准备好投入生产了吗？还是人们努力用它来构建产品？ Francia：Go发布的恰逢其时。有很多Go的基础设计是正确的，但是今天Go中有很多东西不在早期版本中-这在开源中很常见。最明显的是，当时没有“go”命令，所以在如今的Go版本中可以很自然做的事情（例如“go build”）在早期则要困难得多。 提前发布的最大好处是它使社区能够参与Go的设计过程。社区为Go的成功做出了很大的贡献。 我们的Go的第一个公开发行版就可以应用于生产环境了，这表现在用Go构建的程序在生产环境中的高性能和稳定的，但是Go仍然缺乏很多完善之处，Go团队和社区随后可以共同塑造和打磨。 InfoQ：回顾一下，构建Go时需要解决的最技术性问题是什么？ Francia：这个问题很难讲。这有点暗示我们已经完成了Go。我认为Go项目多年来解决了许多“最棘手”的技术问题，我们将继续解决非常具有挑战性的技术问题。我们目前正在努力为Go添加泛型支持。添加泛型本身就是一项艰巨的任务，但是我们也希望它仍然看起来像Go，这意味着使用泛型可以提高可读性。这是一件非常困难的事情，而且我们的一些关键人员已经思考了十多年。 在过去的几年中，我们解决了有关如何管理Go依赖的一些最大挑战。我们在Go中添加了module支持，但却没有引入菱形依赖项或依赖项地狱，这是以前的编程语言所没能做到过的。 另一个挑战是Go在每个版本中持续改进其性能。其体现之一是将垃圾收集的暂停时间延迟(STW)从几秒减少到几毫秒再到几微秒。这对于Go而言是具有变革性的，对于其在服务中的成功至关重要。 InfoQ：如果您必须重新实现一次Go，您会采取什么不同的措施？为什么？ Francia：借助事后观察的优势，作为今天帮助塑造Go的人，但在最初的几年中我并没有出现，我真的不会改变。这是一种美丽的，经过深思熟虑的语言，虽然它并不完美，但使用起来非常好。 我希望我们进行一些小调整，但讨论它们会把太多的焦点放在这些微不足道的事情上。相反，如果我们可以重来一次，我希望我们会犯同样的错误，只是更早而已。Go的发展速度非常快，大约每18个月，Go的用户群的规模就会增加一倍。这意味着，今天与五年前相比，一个变化会影响大约10倍的人。 今天的Go依赖管理机制非常棒，但它可能比预期的晚了五年。这种延误使本来已经很困难的问题变得更加困难，结果给社区造成了不必要的压力。 同样，我们现在正在努力进行的重大语言更改是泛型。这将对社区产生重大影响。如果我们能够重新做一遍，而事后才明白此功能的重要性，我希望我们早在七年前就可以认真地开始这项工作。 InfoQ：Go编程语言还缺少什么？ Francia：作为一种语言，泛型确实是我们所缺少的唯一主要功能，正如我之前所说，我们目前正专注于此。现在有一个支持新泛型语法的playground，您可以在其中使用新泛型语法原型并提供反馈。 除此之外，大部分要做的工作是改进和完善，主要是在语言本身的周边。对于工具，我们计划改善创作，发布和编辑体验。我们还致力于帮助人们做出有关其依赖关系的更好决策。 InfoQ：Go始于Google，但现在是开源的。如今，谁才是幕后的决策人呢？ Francia：2020年11月，Go庆祝了自己开源11周年。Go有一个定义明确的提案流程决定了整个项目的方向。想法和经验来自社区的每个角落。它们作为提案发布到Github上的项目中。从那里社区可以评估他们对提案的看法，并帮助进一步完善提案。提案委员会每周开会，审查未完成的提案。目前，委员会有六名成员，其中四名是Google员工。但决策几乎总是来自社区对提案问题本身的讨论。除非问题讨论明确同意，否则该提议将被拒绝。通过设计和意图，Go的更改会在公开环境中缓慢而有意识地发生。该过程旨在加强这一点。 InfoQ：随着Go的普及，Go的生态系统如何演变？Go最初主要专注于网络和基础架构。这些年来其用法是如何演变的？ [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/go-language-13th-anniversary-by-steve-francia.jpg" alt="img{512x368}" /></p>
<p>本文翻译自<a href="https://www.infoq.com/articles/go-language-13-years/">《Go Language at 13 Years: Ecosystem, Evolution, and Future in Conversation with Steve Francia》</a>。</p>
<blockquote>
<p>译注：Go开源于2009年，如果从那时算起，<a href="https://mp.weixin.qq.com/s/woQeEQUhOLJ7KSE5rm5q6g">Go才11岁</a>；但在Go核心开发团队眼中，Go的真正诞生年份是2007年，至今13个年头了。关于Go的演化简史可以参见我的专栏文章：<a href="https://www.imooc.com/read/87/article/2320">《Go语言的前生今世》</a>。</p>
</blockquote>
<p>本文要点：</p>
<ul>
<li><a href="https://www.imooc.com/read/87/article/2321">Go的简单性</a>让你可以快速上手使用它&#8211;你可以在一个下午就消化掉整个<a href="https://tip.golang.org/ref/spec">Go语言规范</a>；</li>
<li>作者认为Go是当今最好的现代语言之一（其他的还包括：Dart、Flutter和Rust）；</li>
<li>Go的未来是由它的开源社区决定的，它对所有的功能建议进行讨论和辩论。除非达成明确的共识，否则该功能不会被实现。</li>
<li>社区的规模大约每18个月翻一番。</li>
<li>最初，Go的早期采用者多来自python或ruby等动态语言的开发人员，现在随着语言的成熟，来自Java、.NET和C++程序员也开始接纳并使用Go。</li>
<li>在充满挑战的一年里，社区适应了相互支持，出现了多个meetup，并出现了新的资源。</li>
</ul>
<hr />
<p>编程语言的历史只朝着一个方向发展，每一种新的语言的出现都让事情都变得越来越复杂，越来越抽象。然而，就在十几年前，Go在Google诞生了。这种编程语言走的是另外一条路，它把赌注押在了简单和精心的设计和实现上。这个配方一直保留到今天，你可以直接开始写Go代码，没有太大的障碍。当你想到现代软件的大部分流行和可靠的作品都是用Go编写的，比如Docker、Kubernetes、Prometheus等，这就足以让你印象深刻。这个列表还在持续增加。为了了解Go从哪里来，更重要的是它要往哪里去，InfoQ联系了Google负责战略和产品的Go编程语言团队核心成员<a href="https://github.com/spf13">Steve Francia</a>(译注：他也是知名静态站点生成工具<a href="https://github.com/gohugoio/hugo">gohugo</a>的作者)。</p>
<p>InfoQ：非常感谢您抽出宝贵时间回答读者的几个问题。我们能否首先请您介绍一下自己并描述您在Google的角色和日常工作？</p>
<blockquote>
<p>Steve Francia：我是Steve Francia，是Google Go编程语言团队的核心成员，负责产品和策略。</p>
</blockquote>
<p>InfoQ：您将技术挑战和工程挑战归因于十三年前点燃了Go的火花。还有其他吗？当时Google的官方编程语言是什么，缺少什么？</p>
<blockquote>
<p>Francia：创建Go的主要动机是认识到我们的系统已经变得越来越复杂。为了跟上“Google规模”的指数增长，我们设计了复杂的系统来满足我们的需求。随着时间的流逝，我们又在这些基础系统/库和语言的基础上构建了新的复杂系统。人们通常不会想到复杂性的隐性成本。事实是，代码被读取的次数比其编写的次数多。复杂性给团队效率带来了极大的负担。相反，Go很简单。你仅需要花一个下午的时间来学习。Go代码非常简单易读。这种简单性使团队能够以前所未有的方式进行协作。</p>
</blockquote>
<p>InfoQ：这一切是如何开始的？是自上而下的请求（管理人员要求一种语言来满足需求），还是自下而上的请求？来自Google的20％著名的创新？工程师尽其所能-解决问题？</p>
<blockquote>
<p>Francia：没人要求过。这实际上不是一个20％的项目。是一次谈话导致一个研究项目获得了关注，并且被广泛采用，超出了所有人的想象。当然，Google从上到下都对寻找降低复杂性和提高生产力的方法感兴趣。</p>
</blockquote>
<p>InfoQ：在起步阶段，有一种说法是，如果您在发布之日不为自己的产品感到羞耻，那么您可能为时已晚。Go于2011年发布1.0版本，当时Google为了支持它，将其添加到Google App Engine中，YouTube也开始使用Vitess(译注：一种Go实现的Mysql前置代理，用于建立mysql集群）。Go在发布时就已经准备好投入生产了吗？还是人们努力用它来构建产品？</p>
<blockquote>
<p>Francia：Go发布的恰逢其时。有很多Go的基础设计是正确的，但是今天Go中有很多东西不在早期版本中-这在开源中很常见。最明显的是，当时没有“go”命令，所以在如今的Go版本中可以很自然做的事情（例如“go build”）在早期则要困难得多。</p>
<p>提前发布的最大好处是它使社区能够参与Go的设计过程。社区为Go的成功做出了很大的贡献。</p>
<p>我们的Go的第一个公开发行版就可以应用于生产环境了，这表现在用Go构建的程序在生产环境中的高性能和稳定的，但是Go仍然缺乏很多完善之处，Go团队和社区随后可以共同塑造和打磨。</p>
</blockquote>
<p>InfoQ：回顾一下，构建Go时需要解决的最技术性问题是什么？</p>
<blockquote>
<p>Francia：这个问题很难讲。这有点暗示我们已经完成了Go。我认为Go项目多年来解决了许多“最棘手”的技术问题，我们将继续解决非常具有挑战性的技术问题。我们目前正在努力<a href="https://mp.weixin.qq.com/s/SMT40557JgQ9FjUkswznlA">为Go添加泛型支持</a>。添加泛型本身就是一项艰巨的任务，但是我们也希望它仍然看起来像Go，这意味着使用泛型可以提高可读性。这是一件非常困难的事情，而且我们的一些关键人员已经思考了<a href="https://mp.weixin.qq.com/s/do7slOGxztgAfx4Io4PQkg">十多年</a>。</p>
<p>在过去的几年中，我们解决了有关如何管理Go依赖的一些最大挑战。我们在Go中<a href="https://mp.weixin.qq.com/s/fg84g4OzSgoHDGbvVDbMKg">添加了module支持</a>，但却没有引入菱形依赖项或依赖项地狱，这是以前的编程语言所没能做到过的。</p>
<p>另一个挑战是Go在每个版本中持续改进其性能。其体现之一是将垃圾收集的暂停时间延迟(STW)从几秒减少到几毫秒再到几微秒。这对于Go而言是具有变革性的，对于其在服务中的成功至关重要。</p>
</blockquote>
<p>InfoQ：如果您必须重新实现一次Go，您会采取什么不同的措施？为什么？</p>
<blockquote>
<p>Francia：借助事后观察的优势，作为今天帮助塑造Go的人，但在最初的几年中我并没有出现，我真的不会改变。这是一种美丽的，经过深思熟虑的语言，虽然它并不完美，但使用起来非常好。</p>
<p>我希望我们进行一些小调整，但讨论它们会把太多的焦点放在这些微不足道的事情上。相反，如果我们可以重来一次，我希望我们会犯同样的错误，只是更早而已。Go的发展速度非常快，大约每18个月，Go的用户群的规模就会增加一倍。这意味着，今天与五年前相比，一个变化会影响大约10倍的人。</p>
<p>今天的Go依赖管理机制非常棒，但它可能比预期的晚了五年。这种延误使本来已经很困难的问题变得更加困难，结果给社区造成了不必要的压力。</p>
<p>同样，我们现在正在努力进行的重大语言更改是<a href="https://mp.weixin.qq.com/s/14WeOQBdezWTC5OqQrJtfg">泛型</a>。这将对社区产生重大影响。如果我们能够重新做一遍，而事后才明白此功能的重要性，我希望我们早在七年前就可以认真地开始这项工作。</p>
</blockquote>
<p>InfoQ：Go编程语言还缺少什么？</p>
<blockquote>
<p>Francia：作为一种语言，泛型确实是我们所缺少的唯一主要功能，正如我之前所说，我们目前正专注于此。现在<a href="https://mp.weixin.qq.com/s/14WeOQBdezWTC5OqQrJtfg">有一个支持新泛型语法的playground</a>，您可以在其中使用新泛型语法原型并提供反馈。</p>
<p>除此之外，大部分要做的工作是改进和完善，主要是在语言本身的周边。对于工具，我们计划改善创作，发布和编辑体验。我们还致力于帮助人们做出有关其依赖关系的更好决策。</p>
</blockquote>
<p>InfoQ：Go始于Google，但现在是开源的。如今，谁才是幕后的决策人呢？</p>
<blockquote>
<p>Francia：2020年11月，<a href="https://mp.weixin.qq.com/s/woQeEQUhOLJ7KSE5rm5q6g">Go庆祝了自己开源11周年</a>。Go有一个定义明确的<a href="https://github.com/golang/proposal">提案流程</a>决定了整个项目的方向。想法和经验来自社区的每个角落。它们作为提案发布到Github上的项目中。从那里社区可以评估他们对提案的看法，并帮助进一步完善提案。提案委员会每周开会，审查未完成的提案。目前，委员会有六名成员，其中四名是Google员工。但决策几乎总是来自社区对提案问题本身的讨论。除非问题讨论明确同意，否则该提议将被拒绝。通过设计和意图，Go的更改会在公开环境中缓慢而有意识地发生。该过程旨在加强这一点。</p>
</blockquote>
<p>InfoQ：随着Go的普及，Go的生态系统如何演变？Go最初主要专注于网络和基础架构。这些年来其用法是如何演变的？</p>
<blockquote>
<p>Francia：关于Go的一个有趣的事情是Go语言走了一条与其创始人最初计划不同的途径。Go语言之父们创建Go的最初目的是构建流行的高性能服务器端编程语言（当时为Java和C++）的替代品。创始人们认为，一种简单的语言可以在保持性能的同时，极大地提高此类开发人员的生产率。</p>
<p>尽管Go在争取到了一些Java和C++工程师的支持和早期采纳，但Go的大部分早期采用者都来自动态语言程序员群体，这些语言来自Python，Javascript，Ruby和PHP等语言。事实证明，Go最初对动态语言类的吸引力更大，动态语言类看到了在保持生产力的的同时大幅提高性能的机会。</p>
<p>随着Go及其生态系统的成熟，Go的采用已扩展到企业中，并且Java，C++和C＃工程师的最初受众也加快了他们对Go的采用。</p>
<p>Go的独特魅力之一是，它是一种小语言，其大多数创新就发生在其生态系统中。我们一直对社区采用Go的创造性和多样化方向感到惊讶。Go的优势仍然是Go十分适合的云/服务器应用程序，但事实证明Go确实也非常适合许多其他类型的应用程序。DevOps / SRE，CLI，Web应用程序和数据处理已全部转到Go。现在，我们看到Go用于微控制器，机器人技术，游戏等。</p>
</blockquote>
<p>InfoQ：Kubernetes，Docker和Prometheus都是用Go编写的。还有其他用该语言编写的工具吗？</p>
<blockquote>
<p>Francia：这里能列出的工具太多了。我个人经常使用的一些比较流行的工具是：</p>
<ul>
<li><a href="https://gohugo.io/">Hugo</a>，一个静态网站生成器（我几年前创建的）。</li>
<li><a href="https://syncthing.net/">Syncthing</a>，一种分布式同步工具（请考虑Dropbox / Google驱动器，但不带服务器）。</li>
<li><a href="https://istio.io/">服务网格Istio</a></li>
<li><a href="https://www.terraform.io/">Terraform</a>，基础架构即代码</li>
<li><a href="https://www.influxdata.com/">InfluxDB</a>，时间序列数据库</li>
</ul>
<p>在<a href="https://github.com/avelino/awesome-go#software-packages">Awesome Go</a>上可以找到更详细的列表。</p>
</blockquote>
<p>InfoQ：在网络和系统编程方面，Go是高效且可靠的，但是Go所不适合的领域是什么呢？</p>
<blockquote>
<p>Francia：对我自己来说，今天只有三种现代语言。每种语言都经过精心设计，以解决前代语言的不同缺点，从而使每种语言在不同方面都具有出色的表现，并且是其他语言的很好补充。这是我看这三种语言的方式：</p>
<ul>
<li>Go是一种很好的默认语言。它是系统，服务器，API，守护程序，数据库，网站，工具等的理想选择。Go达到了性能与开发人员生产力之间的关键平衡。</li>
<li>Dart + Flutter，用于基于GUI的应用程序（移动+桌面）。Flutter在编写一个可以在多种操作系统和多种格式下工作的客户端应用程序的想法方面表现出色。</li>
<li>需要精细控制时可以使用Rust。对于低级编程、内核之类的东西，Rust提供了更高的精度，但代价是增加了复杂性。有时候，这种权衡是有意义的，而当这样做时，Rust是一个不错的选择。</li>
</ul>
<p>我认为，未来10年以上的大多数“现代”工作负载将以其中一种语言编写。当然，总会有需要支持的旧工作负载，因此请不要认为我在这里的观点暗示了任何语言的消亡。肯定还存在在某些领域中，诸如R，SQL甚至Javascript之类的利基语言可以发挥作用。</p>
</blockquote>
<p>InfoQ：史蒂夫，我记得几年前在布达佩斯参加了一次会议，在那里您举办了有关使用Go的研讨会。我有种感觉，您会更多向对手推销并建议Go，而不是向朋友-为什么？</p>
<blockquote>
<p>Francia：那是一次很棒的会议，也是我第一次在布达佩斯。从那以后我已经回来过几次了，这是我最喜欢的城市之一，如此充满魅力。</p>
<p>许多年前，我在MongoDB工作。我的角色是领导开发人员体验团队，这意味着我应对与用户相关的一切负责。其中包括文档，网站，开发人员关系，MongoDB界面，以及设计和设计我们与语言和框架的集成。这是一个非常广泛且具有挑战性的角色，需要我的团队使用10多种不同的编程语言（以及几种人类语言）进行编写。到那时为止，我在职业生涯中一直使用多种语言，并以能够为我们的每种语言做出贡献为目标。当时，我认为自己是一个会说多种语言的人，并且很高兴能借此机会扩展自己的经验并了解这些不同的语言。</p>
<p>首先，我们专注于支持最受欢迎的语言，而我一直在寻找“下一种语言”可能是什么。由于马丁·奥德斯基（Martin Odersky）在Scala上的免费在线课程，我学到的第一门“下一门语言”是Scala。我喜欢学习语言，并且一直在搜寻。我尝试的下一种语言是Go。我恋爱了。就像有人为我设计了一种语言。我花了大量的空闲时间，大部分时间每天花3个小时以上，坐火车去曼哈顿，写Go软件。这就是<a href="https://gohugo.io/">Hugo</a>，<a href="https://cobra.dev/">Cobra</a>，<a href="https://github.com/spf13/viper">Viper</a>，<a href="https://github.com/spf13/afero">Afero</a>和许多其他库。</p>
<p>在此过程中，我了解到我不是一个会说多种语言的人，只是我还没有发现自己的语言。从我第一次使用Go的那一刻起，我就沉浸在Go社区和生态系统中，在世界各地进行培训，在许多会议上发表演讲并组织一些活动。在过去的七年中，我一直在告诉任何尝试了解Go语言的人，在此过程中，我以某种方式说服了Go团队和Google让我加入他们。除此之外，我还帮助了无数其他人讲述他们的故事，其中许多故事都在<a href="https://go.dev/">Go.dev</a>上。</p>
</blockquote>
<p>InfoQ：Go语言才13岁，所以还是个少年(译注：在编程语言领域)。你怎么看待这件事？它是可靠的类型，它使用户的生活变得更轻松，还是仍然叛逆而喜怒无常，使操作变得棘手？</p>
<blockquote>
<p>Francia：作为用户，我认为Go从来没有比现在更好。向module的迁移非常顺利。Go非常稳定，性能不断提高。Go工具也越来越好。Go.dev是一个很棒的一站式资源，它将来自整个社区的所有最终用户的参考资料，教程，文档和库集中在一个地方。我可能有偏见，但是作为Go的用户，在加入Go团队很久之前，我对Go的现状和发展方向感到非常满意。</p>
</blockquote>
<p>InfoQ：对于Go开发要使用的工具箱，您会推荐哪些？</p>
<blockquote>
<p>Francia：Go的一大优点是，它真正满足了您的需求。Go开发在Mac，Linux或Windows上几乎完全相同，并且<a href="https://tonybai.com/2014/10/20/cross-compilation-with-golang/">Go的交叉编译</a>使其可为任何架构和OS轻松构建。随着<a href="https://github.com/golang/tools/tree/master/gopls">gopls语言服务器</a>的引入，所有编辑器和IDE都将具有很棒的编写Go语言的体验。Go发行版中附带的Go工具包含开发人员开始使用该语言所需的一切。</p>
<p>尽管我主要在Windows上使用VSCodium或Vim进行开发，但我将时间分配在这三个OS之间。我经常使用Cobra工具和库，但是这些天我个人对Go的使用主要是构建一些小的CLI应用程序和实用程序来自动化或简化任务，因此非常适合。</p>
</blockquote>
<p>InfoQ：对于从零开始学习Go的程序员来说，Go的学习曲线有多陡峭？您对新手的建议是什么？</p>
<blockquote>
<p>Francia：正如我之前提到的，Go的最大优势之一就是入门非常容易。人们常常会感到震惊，但这确实是事实-您可以在一个下午阅读并消化整个Go规范。您可以在周末学习Go。在几周内，您将精通Go语言。有些甚至比这快。如果您以其他几种语言的经验来学习该语言，则可以很快选择Go。</p>
<p>当我们与采用Go的公司会面时，这是他们告诉我们的最一致的内容之一。Go非常容易上手。</p>
</blockquote>
<p>InfoQ：对于新手而言，学习Go的前提是什么？</p>
<blockquote>
<p>Francia：老实说，只是时间和兴趣。Go适合所有人。来自社区的<a href="https://go.dev/">go.dev</a>上有一些很棒的入门资源。</p>
</blockquote>
<p>InfoQ：Go的发展让所有人（包括您自己）都感到惊讶。在接下来的十年中，您认为Go会如何发展？</p>
<blockquote>
<p>Francia：如果回顾一下计算机编程语言的历史，我们会发现绝大多数主流编程语言将在其15至20年间大步前进。Java，Python，Ruby，JavaScript和许多其他语言都是如此。自诞生以来的13年中，Go奠定了坚实的基础，并正在成为主流语言。Go的杰出之处在于可以同时提供高性能和高开发人员生产力。</p>
<p>在接下来的10年中，向云计算的大规模转变只会继续加速。公司希望缩短上市时间，降低运营成本并提高安全性。迁移的第一阶段将主要是将其现有工作负载迁移到云中。Go在这里起着关键的支持作用，提供API桥接能力，以使“传统”工作负载能够在云服务上运行。第二个更重要的阶段将是行业转变为利用独特的云产品，逐渐转向云原生应用程序开发。在这些情况下，Go是明智的选择。</p>
<p>所有云提供商都在Go中编写其关键基础架构。随着公司寻求现代化，有哪家公司不想使用一种安全可靠的语言以及经过十多年来来自全球一些最大公司的关键工作负载的测试，既可以降低开发成本，又可以大大降低其运营成本的语言呢？简而言之，Go将成为云开发的代名词，而云开发将发展成为该行业绝大多数的业务。</p>
</blockquote>
<p>InfoQ：我应该问你什么，但没有问？</p>
<blockquote>
<p>Francia：谈论一种语言而不谈论其社区是不可能的。实际上，Go之所以存在，是因为全世界有数百万人使用Go开发。Go社区强大，热情且多样化。与所有人一样，今年Go社区进行了调整，并且也做了调整。在世界各地，gopher聚在一起并互相帮助。召开了30次<a href="https://www.meetup.com/pro/go">（虚拟）会议</a>。数百次聚会（主要是虚拟聚会）以及<a href="https://www.reddit.com/r/golang/">/r/golang</a>和<a href="https://gophers.slack.com/messages/general/">Gopher slack</a>的参与度显着增长。我们启动了两个值得注意的新的社区主导程序，以帮助新的Gophers <a href="https://play-with-go.dev/">play-with-go.dev</a>和<a href="https://promo.qooper.io/organizations/MjE1">mentoring.gobridge.org</a>。</p>
<p>我们感谢世界上所有为Go蓬勃发展的生态系统做出贡献的Gopher，并共同期待Go的美好未来。</p>
</blockquote>
<hr />
<h3>“Gopher部落”，新年新气象</h3>
<p><a href="https://public.zsxq.com/groups/51284458844544">“Gopher部落”</a>正式转正（从试运营星球变成了正式星球）！“gopher部落<br />
”旨在打造一个精品Go学习和进阶社群，目前虽小，但持续力很强。在2021年上半年，部落将策划两个专题系列分享，并且是部>落独享哦：</p>
<ul>
<li>Go技术书籍的书摘和读书体会系列</li>
<li>Go与eBPF系列</li>
</ul>
<p>考虑到部落尚处于推广期，这里仍然为大家准备了新人优惠券，虽然优惠幅度有所下降，但依然物超所值，早到早享哦！</p>
<p><img src="http://image.tonybai.com/img/202011/gopher-tribe-zsxq.png" alt="" /></p>
<p>感谢大家对本星球的支持！</p>
<p>Go技术专栏“<a href="https://www.imooc.com/read/87">改善Go语⾔编程质量的50个有效实践</a>”正在慕课网火热热销中！本专栏主要满足广大gopher关于Go语言进阶的需求，围绕如何写出地道且高质量Go代码给出50条有效实践建议，上线后收到一致好评！欢迎大家订阅！</p>
<p><img src="http://image.tonybai.com/img/202011/go-column-pgo-with-qr-and-text.png" alt="" /></p>
<p>我的网课“<a href="https://coding.imooc.com/class/284.html">Kubernetes实战：高可用集群搭建、配置、运维与应用</a>”在慕课网热卖中，欢迎小伙伴们订阅学习！</p>
<p><img src="https://tonybai.com/wp-content/uploads/k8s-practice-with-qr-and-text.png" alt="img{512x368}" /></p>
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/。smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。2020年4月8日，中国三大电信运营商联合发布《5G消息白皮书》，51短信平台也会全新升级到“51商用消息平台”，全面支持5G RCS消息。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻)归档仓库 &#8211; https://github.com/bigwhite/gopherdaily</p>
<p>我的联系方式：</p>
<ul>
<li>微博：https://weibo.com/bigwhite20xx</li>
<li>微信公众号：iamtonybai</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>“Gopher部落”知识星球：https://public.zsxq.com/groups/51284458844544</li>
</ul>
<p>微信赞赏：<br />
<img src="https://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2021, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2021/01/02/go-language-13-years/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello，Termux</title>
		<link>https://tonybai.com/2017/11/09/hello-termux/</link>
		<comments>https://tonybai.com/2017/11/09/hello-termux/#comments</comments>
		<pubDate>Thu, 09 Nov 2017 13:51:58 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[AArch64]]></category>
		<category><![CDATA[addon]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[apk4fun]]></category>
		<category><![CDATA[apt]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[connectbot]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[F-Droid]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go1.9.2]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[hacker's-keyboard]]></category>
		<category><![CDATA[id_rsa.pub]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[logitech]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[MIX2]]></category>
		<category><![CDATA[neocomplete]]></category>
		<category><![CDATA[oh-my-zsh]]></category>
		<category><![CDATA[openssh]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[sources.list]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[sshd]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[terminal-emulator]]></category>
		<category><![CDATA[Terminal-Emulator-for-Android]]></category>
		<category><![CDATA[termux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[ultisnips]]></category>
		<category><![CDATA[UTF8]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vim-go]]></category>
		<category><![CDATA[vim8.0]]></category>
		<category><![CDATA[vt100]]></category>
		<category><![CDATA[zsh]]></category>
		<category><![CDATA[安卓]]></category>
		<category><![CDATA[极客]]></category>

		<guid isPermaLink="false">http://tonybai.com/?p=2454</guid>
		<description><![CDATA[程序员或多或少都有一颗Geek(极客)的心^0^。- Tony Bai 折腾开始。 这一切都源于前不久将手机换成了Xiaomi的MIX2。因为青睐开放的系统（相对于水果公司系统的封闭，当然Mac笔记本除外^0^），我长期使用Android平台的手机。但之前被三星Note3手机的“大屏”搞的不是很舒服，这两年一直用5寸及以下的手机，因为单手操作体验良好。MIX2的所谓“全面屏”概念又让我回归到了大屏时代。 除了大屏，现在手机“豪华”的硬件配置也让人惊叹：高通骁龙835，8核，最高主频 2.45GHz；6GB以上的LPDDR4x的双通道大内存，怪不得微软和高通都开始合作生产基于高通ARM处理器的Win10笔记本了，这配置支撑在笔记本上办公+浏览网页绰绰有余。不过对于不怎么玩游戏的我而言，这种配置仅仅用作手机日常功能有些浪费。于是有了“mobile coding”的想法和需求，至少现在是这样想的，冲动也好，伪需求也好，先实现了再说。 一、神器Termux，不仅仅是一个terminal emulator 所谓”mobile coding”不仅仅是要通过手机ssh到服务器端进行coding，还要支持在手机上搭建一个dev环境。dev环境这个需求是以往我安装的ConnectBot等ssh client端工具所无法提供的，而其他一些terminal工具，诸如Terminal Emulator for Android仅仅提供一些shell命令的支持，适合于那些喜爱使用命令行对Android机器进行管理的”administrator”们，但对dev环境的搭建支持有限的。于是神器Termux登场了。 Termux是什么？Termux首先是一个Android terminal emulator，可以像那些terminal工具一样，提供基本的shell操作命令；除此之外更为重要的是它不仅仅是一个terminal emulator。Termux提供了一套模拟的Linux环境，你可以在无需root、无需root、无需root的情况下，像在PC linux环境下一样进行各种Linux操作，包括使用apt工具进行安装包管理、定制shell、访问网络、编写源码、编译和运行程序，甚至将手机作为反向代理、负载均衡服务器或是Web服务器，又或是做一些羞羞的hack行为等。 1、安装 Termux仅支持Android 5.0及以上版本（估计现在绝大多数android机都满足这一条件）。在国内建议使用F-Droid安装Termux（先下载安装F-Droid，再在F-Droid内部搜索Termux，然后点击安装），国内的各种安装助手很少有对这个工具的支持。或是到apk4fun下载Termux的apk包（size非常小）到手机中安装(安装时需要连接着网络)。当前Termux的最新版本为0.54。 在桌面点击安装后的Termux图标，我们就启动了一个Termux应用，见下图： 2、Termux初始环境探索 Mix2手机的Android系统使用的是Android 7.1.1版本，桌面Launcher用的是MIUI 9.1稳定版，默认的shell是bash。通过Termux，我们可以查看Android 7.1.1.使用的Linux内核版本如下： $uname -a Linux localhost 4.4.21-perf-g6a9ee37d-06186-g2b2a77b #1 SMP PREEMPT Thu Oct 26 14:55:45 CST 2017 aarch64 Android 可以看出Linux内核是4.4.21，采用的CPU arch family是ARM aarch64。 我再来看一下Termux提供的常见目录结构： Home路径： $cd ~/ $pwd [...]]]></description>
			<content:encoded><![CDATA[<p><strong><em>程序员或多或少都有一颗<a href="https://en.wikipedia.org/wiki/Geek">Geek(极客)</a>的心^0^。- Tony Bai</em></strong></p>
<p>折腾开始。</p>
<p>这一切都源于前不久将手机换成了Xiaomi的<a href="https://en.wikipedia.org/wiki/Xiaomi_Mi_MIX_2">MIX2</a>。因为青睐开放的系统（相对于水果公司系统的封闭，当然Mac笔记本除外^0^），我长期使用<a href="https://en.wikipedia.org/wiki/Android_(operating_system)">Android平台</a>的手机。但之前被三星Note3手机的“大屏”搞的不是很舒服，这两年一直用5寸及以下的手机，因为单手操作体验良好。MIX2的所谓“全面屏”概念又让我回归到了大屏时代。</p>
<p>除了大屏，现在手机“豪华”的硬件配置也让人惊叹：高通骁龙835，8核，最高主频 2.45GHz；6GB以上的LPDDR4x的双通道大内存，怪不得微软和高通都开始合作生产基于高通ARM处理器的Win10笔记本了，这配置支撑在笔记本上办公+浏览网页绰绰有余。不过对于不怎么玩游戏的我而言，这种配置仅仅用作手机日常功能有些浪费。于是有了“mobile coding”的想法和需求，至少现在是这样想的，冲动也好，伪需求也好，先实现了再说。</p>
<h2>一、神器Termux，不仅仅是一个terminal emulator</h2>
<p>所谓”mobile coding”不仅仅是要通过手机ssh到服务器端进行coding，还要支持在手机上搭建一个dev环境。dev环境这个需求是以往我安装的<a href="https://github.com/connectbot/connectbot">ConnectBot</a>等ssh client端工具所无法提供的，而其他一些terminal工具，诸如<a href="https://github.com/jackpal/Android-Terminal-Emulator">Terminal Emulator for Android</a>仅仅提供<a href="https://github.com/jackpal/Android-Terminal-Emulator/wiki/Android-Shell-Command-Reference">一些shell命令</a>的支持，适合于那些喜爱使用命令行对Android机器进行管理的”administrator”们，但对dev环境的搭建支持有限的。于是神器<a href="https://termux.com/">Termux</a>登场了。</p>
<p><a href="https://github.com/termux/termux-app">Termux</a>是什么？Termux首先是一个Android terminal emulator，可以像那些terminal工具一样，提供基本的shell操作命令；除此之外更为重要的是它不仅仅是一个terminal emulator。Termux提供了一套模拟的<a href="http://tonybai.com/tag/linux">Linux</a>环境，你可以在<strong>无需root、无需root、无需root</strong>的情况下，像在PC linux环境下一样进行各种Linux操作，包括使用<a href="https://en.wikipedia.org/wiki/APT_(Debian)">apt工具</a>进行安装包管理、定制shell、访问网络、编写源码、编译和运行程序，甚至将手机作为反向代理、负载均衡服务器或是Web服务器，又或是做一些羞羞的hack行为等。</p>
<h3>1、安装</h3>
<p>Termux仅<a href="https://github.com/termux/termux-app/issues/6">支持Android 5.0及以上版本</a>（估计现在绝大多数android机都满足这一条件）。在国内建议使用<a href="https://f-droid.org/packages/com.termux/">F-Droid</a>安装Termux（先下载安装F-Droid，再在F-Droid内部搜索Termux，然后点击安装），国内的各种安装助手很少有对这个工具的支持。或是到<a href="https://www.apk4fun.com/apk/74133/">apk4fun</a>下载Termux的apk包（size非常小）到手机中安装(安装时需要连接着网络)。当前Termux的最新版本为<a href="https://github.com/termux/termux-app/releases/tag/v0.54">0.54</a>。</p>
<p>在桌面点击安装后的Termux图标，我们就启动了一个Termux应用，见下图：</p>
<p><img src="http://tonybai.com/wp-content/uploads/termux-initial-start.jpg" alt="img{512x368}" /></p>
<h3>2、Termux初始环境探索</h3>
<p>Mix2手机的Android系统使用的是<a href="https://www.android.com/phones/">Android 7.1.1版本</a>，桌面Launcher用的是<a href="https://en.wikipedia.org/wiki/MIUI">MIUI 9.1</a>稳定版，默认的shell是<a href="http://tonybai.com/2009/02/27/make-bash-my-default-shell/">bash</a>。通过Termux，我们可以查看Android 7.1.1.使用的<a href="http://tonybai.com/2012/03/15/linux-kernel-hacking-series-kernel-config-compile-and-install/">Linux内核</a>版本如下：</p>
<pre><code>$uname -a
Linux localhost 4.4.21-perf-g6a9ee37d-06186-g2b2a77b #1 SMP PREEMPT Thu Oct 26 14:55:45 CST 2017 aarch64 Android
</code></pre>
<p>可以看出<a href="http://tonybai.com/2012/03/15/linux-kernel-hacking-series-kernel-config-compile-and-install/">Linux内核</a>是4.4.21，采用的CPU arch family是<a href="https://en.wikipedia.org/wiki/ARM_architecture">ARM</a> <a href="https://en.wikipedia.org/wiki/ARM_architecture#AArch64_features">aarch64</a>。</p>
<p>我再来看一下Termux提供的常见目录结构：</p>
<p>Home路径：</p>
<pre><code>$cd ~/
$pwd
/data/data/com.termux/files/home

//或者通过环境变量HOME获取：

$echo $HOME
/data/data/com.termux/files/home
</code></pre>
<p>长期使用Linux的朋友可能会发现，这个HOME路径好是奇怪，一般的标准<a href="https://en.wikipedia.org/wiki/Linux_distribution">Linux发行版</a>，比如<a href="http://tonybai.com/tag/ubuntu">Ubuntu</a>都是在”/home”下放置用户目录，但termux环境中HOME路径却是一个<strong>奇怪的位置</strong>。在<a href="https://wiki.termux.com/wiki/Main_Page">Termux官方Wiki</a>中，我们得到的答案是：Termux是一个prefixed system。</p>
<blockquote>
<p>这个prefix的含义我理解颇有些类似于我们在使用configure脚本时指定的&#8211;prefix参数的含义。我们在执行configure脚本时，如果不显式地给&#8211;prefix传入值，那么make install后，包将被install在<strong>标准位置</strong>；否则将被install在&#8211;prefix值所指定的位置。</p>
</blockquote>
<p>prefixed system意味着Termux中所有binaries、libraries、configs都不是放在标准的位置，比如：/usr/bin、/bin、/usr/lib、/etc等下面。Termux expose了一个特殊的环境变量:PREFIX（类似于configure &#8211;prefix参数选项)：</p>
<pre><code>$echo $PREFIX
/data/data/com.termux/files/usr

$cd $PREFIX
$ls -F
bin/  etc/  include/  lib/  libexec/  share/  tmp/  var/
</code></pre>
<p>是不是有些似曾相识？但Termux的$PREFIX路径与标准linux的根路径下的目录结构毕竟还<a href="https://wiki.termux.com/wiki/Differences_from_Linux">存在差别</a>，但有着对应关系，这种对应关系大致是：</p>
<pre><code>Termux的$PREFIX/bin  &lt;=&gt;  标准Linux环境的 /bin和/usr/bin
Termux的$PREFIX/lib  &lt;=&gt;  标准Linux环境的 /lib和/usr/lib
Termux的$PREFIX/var  &lt;=&gt;  标准Linux环境的 /var
Termux的$PREFIX/etc  &lt;=&gt;  标准Linux环境的 /etc
</code></pre>
<p>因此，基本可以认为Termux的$PREFIX/就对应于标准Linux的/路径。</p>
<h3>3、更新源和包管理</h3>
<p>Termux的牛逼之处在于它基于debian的<a href="https://en.wikipedia.org/wiki/APT_(Debian)">APT包</a>管理工具进行软件包的安装、管理和卸载，就像我们在Ubuntu下所做的那样，非常方便。</p>
<p>Termux自己<a href="http://termux.net/">维护了一个源</a>，提供各种专门为termux定制的包：</p>
<pre><code># The main termux repository:
#deb [arch=all,aarch64] http://termux.net stable main
</code></pre>
<p>同时，<a href="https://github.com/termux/termux-packages">termux-packages项目</a>为开发者和爱好者提供了构建工具和脚本，通过这些工具和脚本，我们可以将自己需要的软件包编译为可以在termux运行的版本，并补充到Termux的源之中。我大致测试了一下官方这个源还是可用的，虽然初始连接的响应很缓慢。</p>
<p>国内清华大学维护了一个<a href="https://mirror.tuna.tsinghua.edu.cn/help/termux/">Termux的镜像源</a>，你可以通过编辑 /data/data/com.termux/files/usr/etc/apt/sources.list文件或执行apt edit-sources命令编辑源(在Shell配置中添加export EDITOR=vi后，apt edit-sources才能启动编辑器进行编辑)：</p>
<pre><code># The main termux repository:
#deb [arch=all,aarch64] http://termux.net stable main
deb [arch=all,aarch64] http://mirrors.tuna.tsinghua.edu.cn/termux stable main
</code></pre>
<p>剩下的操作与Ubuntu上的一模一样，无非apt update后，利用apt install安装你想要的包。目前Termux源中都有哪些包呢？可以通过apt list命令查看：</p>
<pre><code>$apt list
Listing... Done
aapt/stable 7.1.2.33-1 aarch64
abduco/stable 0.6 aarch64
abook/stable 0.6.0pre2-1 aarch64
ack-grep/stable 2.18 all
alpine/stable 2.21 aarch64
angband/stable 4.1.0 aarch64
apache2/stable 2.4.29 aarch64
apache2-dev/stable 2.4.29 aarch64
apksigner/stable 0.4 all
apr/stable 1.6.3 aarch64
apr-dev/stable 1.6.3 aarch64
apr-util/stable 1.6.1 aarch64
apr-util-dev/stable 1.6.1 aarch64
apt/stable,now 1.2.12-3 aarch64 [installed]
apt-transport-https/stable 1.2.12-3 aarch64
... ...
zile/stable 2.4.14 aarch64
zip/stable 3.0-1 aarch64
zsh/stable,now 5.4.2-1 aarch64 [installed]
</code></pre>
<p>查看是否有需要更新的包列表：</p>
<pre><code>$apt list --upgradable
</code></pre>
<p>以安装<a href="http://tonybai.com/tag/go">golang</a>为例：</p>
<pre><code>$apt install golang
....
$go version
go version go1.9.2 android/arm64
</code></pre>
<p><img src="http://tonybai.com/wp-content/uploads/termux-apt-install-go.jpg" alt="img{512x368}" /></p>
<p>Termux源中的包似乎更新的很勤奋，<a href="http://tonybai.com/2017/07/14/some-changes-in-go-1-9/">Go 1.9.2</a>才发布没多久，这里已经是最新版本了，这点值得赞一个！</p>
<h2>二、开发环境搭建</h2>
<p>我的目标是<strong>mobile coding</strong>，需要在Termux上搭建一个dev环境，以<a href="http://tonybai.com/tag/go">Go</a>环境为例。</p>
<h3>1、sshd</h3>
<p>在搭建和配置阶段，如果直接通过Android上的软键盘操作，即便屏再大，那个体验也是较差的。我们最好通过PC连到termux上去安装和配置，这就需要我们在Termux上搭建一个<a href="https://wiki.termux.com/wiki/SSH">sshd server</a>。下面是步骤：</p>
<pre><code>$apt install openssh
$sshd
</code></pre>
<p>就这么简单，一个sshd的server就在termux的后台启动起来了。由于Termux没有root权限，无法listen数值小于1024的端口，因此termux上sshd默认的listen端口是8022。另外termux上的sshd server不支持用户名+密码的方式进行登录，只能用免密登录的方式，即将PC上的~/.ssh/id_rsa.pub写入termux上的~/.ssh/authorized_keys文件中。关于免密登录的证书生成方法和导入方式，网上资料已经汗牛充栋，这里就不赘述了。导入PC端的id_rsa.pub后，PC就可以通过下面命令登录termux了：</p>
<pre><code>$ssh 10.88.46.79  -p 8022
Welcome to Termux!

Wiki:            https://wiki.termux.com
Community forum: https://termux.com/community
IRC channel:     #termux on freenode
Gitter chat:     https://gitter.im/termux/termux
Mailing list:    termux+subscribe@groups.io

Search packages:   pkg search &lt;query&gt;
Install a package: pkg install &lt;package&gt;
Upgrade packages:  pkg upgrade
Learn more:        pkg help
</code></pre>
<p>其中10.88.46.79是手机的wlan0网卡的IP地址，可以在termux中使用ip addr命令获得:</p>
<pre><code>$ip addr show wlan0
34: wlan0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 3000
    ... ...
    inet 10.88.46.79/20 brd 10.88.47.255 scope global wlan0
       valid_lft forever preferred_lft forever
    ... ...
</code></pre>
<h3>2、定制shell</h3>
<p>Termux支持多种<a href="https://wiki.termux.com/wiki/Shells">主流Shell</a>，默认的Shell是<a href="http://tonybai.com/tag/bash">Bash</a>。很多开发者喜欢<a href="https://www.zsh.org/">zsh</a> + <a href="https://github.com/robbyrussell/oh-my-zsh">oh-my-zsh</a>的组合，Termux也是支持的，安装起来也是非常简单的：</p>
<pre><code>$ apt install git
$ apt install zsh
$ git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
$ cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
$ chsh zsh
</code></pre>
<p>与在PC上安装和配置zsh和oh-my-zsh没什么两样，你完全可以按照你在PC上的风格定制zsh的Theme等，我用的就是默认theme，所以也无需做太多变化，顶多定制一下PROMPT(~/.oh-my-zsh/themes/robbyrussell.zsh-theme中的PROMPT变量)的格式^0^。</p>
<h3>3、安装vim-go</h3>
<p>在terminal内进行Go开发，<a href="https://github.com/fatih/vim-go">vim-go</a>是必备之神器。vim-go以及相关自动补齐、snippet插件安装在不同平台上都是大同小异的，之前写过两篇《<a href="http://tonybai.com/2014/11/07/golang-development-environment-for-vim">Golang开发环境搭建-Vim篇</a>》和《<a href="http://tonybai.com/2016/09/08/upgrade-vim-go/">vim-go更新小记</a>》，大家可以参考。</p>
<p>不过这里有一个较为关键的问题，那就是Termux官方源中的vim 8.0缺少了对python和lua的支持：</p>
<pre><code> $vim --version|grep py
+cryptv          +linebreak       -python          +viminfo
+cscope          +lispindent      -python3         +vreplace
$vim --version|grep lua
+dialog_con      -lua             +rightleft       +windows
</code></pre>
<p>而一些插件又恰需要这些内置的支持，比如<a href="https://github.com/SirVer/ultisnips/issues/707">ultisnips</a>需要vim自带py支持；<a href="https://github.com/Shougo/neocomplete.vim">neocomplete</a>又依赖vim的lua支持。这样如果你还想要补齐和snippet特性，你就需要在Termux下面自己编译Vim的源码了（configure时加上对python和lua的支持）。</p>
<h3>4、中文支持</h3>
<p>无论是PC还是Termux使用的都是UTF8的内码格式，但是在安装完vim-go后，我试着用vim编辑一些简单的源码，发现在vim中输入的中文都是乱码。这里通过一个配置解决了该问题：</p>
<pre><code>//~/.vimrc

添加一行：

set enc=utf8

</code></pre>
<p>至于其中的原理，可以参见我N年前写的《<a href="http://tonybai.com/2009/09/28/also-talk-about-vim-charset-configuration/">也谈VIM字符集编码设置</a>》一文。</p>
<h2>三、键盘适配</h2>
<p>现阶段，写代码还是需要键盘输入的（憧憬未来^0^）。</p>
<h3>1、软键盘</h3>
<p>使用原生自带的默认软键盘在terminal中用vim进行coding，那得多执着啊，尤其是在vim大量使用ESC键的情况下（我都没找到原生键盘中ESC键在哪里:(）。不过Termux倒是很具包容心，为原生软键盘提供了扩展支持：用两个上下音量键协助你输入一些原生键盘上没有或者难于输入的符号，比如（全部的模拟按键列表参见<a href="https://wiki.termux.com/wiki/Touch_Keyboard">这里</a>）：</p>
<pre><code>清理屏幕：用volume down + L 来模拟 ctrl + L
结束前台程序：用volume down + C 来模拟 ctrl + C
ESC：用volume up + E 来模拟
F1-F9: 用volume up + 1 ~ 9 来模拟

</code></pre>
<blockquote>
<p>据网友提示：volume up + Q键可以打开扩展键盘键，包括ESC、CTRL、ALT等，感谢。</p>
</blockquote>
<p>这样仅能满足临时的需要，要想更有效率的输入，我们需要<a href="https://github.com/klausw/hackerskeyboard">Hacker&#8217;s Keyboard</a>。顾名思义，Hacker&#8217;s Keyboard可以理解为专为Coding(无论出于何种目的)的人准备的。和Termux一样，你可以从<a href="https://f-droid.org/packages/org.pocketworkstation.pckeyboard/">F-droid</a>安装该工具。启动该app后，app界面上有明确的使用说明，如果依旧不明确，还可以查看这篇图文并茂的文章：《<a href="https://www.wikihow.com/Use-Hacker%27s-Keyboard">How to Use Hacker&#8217;s Keyboard</a>》。默认情况下，横屏时Hacker&#8217;s keyboard会使用”Full 5-row layout”，即全键盘，竖屏时，则是4-row layout。你可以通过“系统设置”中的“语言和输入法”配置中对其进行设置，让Hacker&#8217;s keyboard无论在横屏还是竖屏都采用全键盘（我们屏幕够大^0^）：</p>
<p><img src="http://tonybai.com/wp-content/uploads/termux-hackers-keyboard-landscape.jpg" alt="img{512x368}" /><br />
横屏</p>
<p><img src="http://tonybai.com/wp-content/uploads/termux-hackers-keyboard-portrait.jpg" alt="img{512x368}" /><br />
竖屏</p>
<p>Hacker&#8217;s Keyboard无法支持中文输入，这点是目前的缺憾，不过我个人写代码时绝少使用中文，该问题忽略不计。</p>
<h3>2、外接蓝牙键盘</h3>
<p>Hacker&#8217;s Keyboard虽然一定程度提升了Coding时的输入效率，但也仅是权宜之计，长时间大规模通过软键盘输入依旧不甚可取，外接键盘是必须的。对于手机而言，目前最好的外接连接方式就是蓝牙。蓝牙键盘市面上现在有很多种，我选择了老牌大厂<a href="https://en.wikipedia.org/wiki/Logitech">logitech</a>的<a href="https://www.logitech.com/en-us/product/multi-device-keyboard-k480">K480</a>。这款键盘缺点是便携性差点、按键有些硬，但按键大小适中；而那些超便携的蓝牙键盘普遍键帽太小，长时间Coding的体验是个问题。</p>
<p><img src="http://tonybai.com/wp-content/uploads/termux-mix2-logitech-k480.jpg" alt="img{512x368}" /></p>
<p>Termux对外接键盘的支持也是很好的，除了常规输入，通过键盘组合键Ctrl+Alt与其他字母的组合<a href="https://wiki.termux.com/wiki/Hardware_Keyboard">实现各种控制功能</a>，比如：</p>
<pre><code>ctrl + alt + c =&gt; 实现创建一个新的session；
ctrl + alt + 上箭头/下箭头 =&gt; 实现切换到上一个/下一个session的窗口；
ctrl + alt + f =&gt; 全屏
ctrl + alt +v =&gt; 粘贴
ctrl + alt + +/- =&gt; 实现窗口字体的放大/缩小

</code></pre>
<p>不过，外接键盘和Hacker&#8217;s keyboard有一个相同的问题，那就是针对Termux无法输入中文。我尝试了百度、搜狗等输入法，无论如何切换（正常在其他应用中，通过【shift + 空格】实现中英文切换）均只是输入英文。</p>
<h2>四、存储</h2>
<p>到目前为止，我们提到的路径都在termux的私有的内部存储(private internal storage)路径下，这类存储的特点是termux应用内部的、私有的，一旦termux被卸载，这些数据也将不复存在。Android下还有另外两种存储类型：shared internal storage和external storage。所谓shared internal storage是手机上所有App可以共享的存储空间，放在这个空间内的数据不会因为App被卸载掉而被删除掉；而外部存储(external storage)主要是指外部插入的SD Card的存储空间。</p>
<p>默认情况下，Termux只支持private internal storage，意味着你要做好数据备份，否则一旦误卸载termux，数据可就都丢失了;数据可以用git进行管理，并sync到云端。</p>
<p>Termux提供了一个名为<a href="https://github.com/termux/termux-packages/blob/master/packages/termux-tools/termux-setup-storage">termux-setup-storage</a>的工具，可以让你在Termux下访问和使用shared internal storage和external storage；该工具是<a href="https://github.com/termux/termux-packages/tree/master/packages/termux-tools">termux-tools</a>的一部分，你可以通过apt install termux-tools来安装这些工具。</p>
<p>执行termux-setup-storage(注意：这个命令只能在手机上执行才能弹出授权对话框，通过远程ssh登录后执行没有任何效果)时，手机会弹出一个对话框，让你确认授权：</p>
<p><img src="http://tonybai.com/wp-content/uploads/termux-setup-storage.jpg" alt="img{512x368}" /></p>
<p>一旦授权，termux-setup-storage就会在HOME目录下建立一个storage目录，该目录下的结构如下：</p>
<pre><code>➜  /data/data/com.termux/files/home $tree storage
storage
├── dcim -&gt; /storage/emulated/0/DCIM
├── downloads -&gt; /storage/emulated/0/Download
├── movies -&gt; /storage/emulated/0/Movies
├── music -&gt; /storage/emulated/0/Music
├── pictures -&gt; /storage/emulated/0/Pictures
└── shared -&gt; /storage/emulated/0

6 directories, 0 files
</code></pre>
<p>我们看到在我的termux下，termux-setup-storage在storage下建立了6个符号链接，其中shared指向shared internal storage的根目录，即/storage/emulated/0；其余几个分别指向shared下的若干功能目录，比如：相册、音乐、电影、下载等。我的手机没有插SD卡，可能也不支持（市面上大多数手机都已经不支持了），如果插了一张SD卡，那么termux-setup-storage还会在storage目录下j建立一个符号链接指向在external storage上的一个termux private folder。</p>
<p>现在你就可以把数据放在shared internal storage和external storage上了，当然你也可以在Termux下自由访问shared internal storage上的数据了。</p>
<h2>五、小结</h2>
<p>Termux还设计了支持扩展的Addon机制，支持通过各种Addon来丰富Termux功能，提升其能力，这些算是高级功能，在这篇入门文章里就先不提及了。好了，接下来我就可以开始我的mobile coding了，充分利用碎片时间。后续在使用Termux+k480的过程中如果遇到什么具体的问题，我再来做针对性的解析。</p>
<hr />
<p>微博：<a href="http://weibo.com/bigwhite20xx">@tonybai_cn</a><br />
微信公众号：iamtonybai<br />
github.com: https://github.com/bigwhite</p>
<p style='text-align:left'>&copy; 2017, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2017/11/09/hello-termux/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
