关于 Tony Bai | 白明

先后供职于国内某大型软件公司和某创业型数据与基础设施服务公司。先后贡献了lcut、cbehave、buildc多个工具框架。

RSS 地址: https://tonybai.com/feed/

请复制 RSS 到你的阅读器,或快速订阅到 :

Tony Bai | 白明 RSS 预览

智能时代临近:我眼中AI编程的现在与未来

2024-10-14 21:04:30

本文永久链接 – https://tonybai.com/2024/10/14/programming-in-ai-era 自2022年末ChatGPT发布以来,人工智能(AI)正在深刻地改变软件开发的格局。从简单的代码补全到复杂的逻辑生成,AI正逐渐成为程序员不可或缺的助手。最近,OpenAI首席执行官山姆·奥特曼在其个人博客中发表的文章《智能时代》(The Intelligence Age)更让我们深切体会到,超级智能似乎离我们越来越近了。 正如100年前的打孔卡编程方式与现今编程方式的天壤之别,如今的我们也难以完全预见超级AI时代的编程模式。尽管现阶段的大语言模型(如ChatGPT、Claude等)在AI辅助编程方面已经展现出强大的能力,并显著提升了开发效率,但它们仍面临诸多挑战。不过,与打孔卡时代的程序员相比,我们这一代程序员是幸运的,因为我们已经嗅到了超级AI的气息。 当前AI辅助编程的现状 目前,AI辅助编程主要有三种模式: IDE模式:通过使用工具(如Cursor等)智能分析代码上下文,仅需简单的TAB键操作即可生成代码片段甚至是完整代码,显著提高编程效率。 Prompt模式:开发者提供描述性的prompt,AI据此生成代码块,然后开发者将其整合到项目中。这种模式要求开发者对prompt撰写有较高的理解与能力。 Agent模式:在这种模式下,AI作为自主的编程助手,理解开发者的意图并主动规划(强化学习增强的思维链等)和执行任务。开发者可以与AI对话,提出问题或请求功能,而AI则基于上下文自动生成代码、测试用例,甚至进行调试。Agent模式更接近于超级AI的初级模拟,试图通过自然语言交互与上下文理解,模拟人类思维,自主规划并处理复杂编程任务。 虽然IDE和Agent模式本质上都是Prompt模式的变种,但Agent模式更像是对超级AI的初级尝试,使开发者能够更专注于高层设计,将重复性任务交给AI处理。 不过,这三种模式都属于初级辅助模式,虽然已经能显著提升开发效率。这些模式的辅助效能还与多种因素相关,比如: 人类提示工程(Prompt engineering )水平:开发者如何有效地与AI沟通需求,直接影响输出质量。 AI对不同编程语言的掌握和擅长程度:这与AI训练时使用的语料丰富程度和训练方法密切相关。日常实践中事实也证明,像Rust这样语法复杂的语言,AI生成的代码可能更容易出现编译错误。相比之下,Go语言生成的代码往往更容易直接运行。 编程任务的特性:不同类型的编程任务可能更适合不同的AI辅助方式。 注:随着AI在推理方面的提升(乃至形成独立的推理层),“过提示工程”可能不仅无法提高推理性能,还有可能妨碍模型工作。也就是说对于推理能力越来越强的大模型,反倒是提示词越简洁越好,因为思维链都隐藏到了模型内部,如果再用思维链提示反而会适得其反。 当前AI的局限性与未来展望 当前的AI系统更像是一个知识数据库,主要基于已有的知识进行推理,与现实世界的互动能力仍然有限,如缺乏访问互联网和本地系统的能力。这种限制导致AI只能生成代码,却无法验证其逻辑是否正确或者能否编译运行。此外,AI与人类的交互手段仍相对初级,大多局限于文本、图片或语音的形式,这些方式在面对复杂需求时显得笨拙。 那么未来理想的AI辅助编程模式应该是什么样的呢?我认为应是端到端编程,即通过多种交互手段(自然语言、语音、图片以及将来的未知方式等)输入需求,AI直接输出已部署完毕且可正确运行的完整程序。在超级AI时代,这种编程模式将成为现实,届时AI与程序员的交互方式将迎来革命性变化。 我们可以将当前阶段称为”AI的过渡时代“。正如OpenAI的Sam Altman所预言那样,真正的智能时代可能还需要几千天才能到来。在这个超级AI出现的时代,端到端的编程模式可能才会真正实现。 根据Sequoia Capital的最新研究报告,AI技术正在从”快速思考”(System 1)向”慢速思考”(System 2)演进。System 1指的是快速、直觉性的反应,而System 2则涉及更深层次的推理和问题解决能力。这种演进正在推动一种新的”推理层”的发展,这可能是通向真正智能时代的关键一步: 来自Sequoia Capital的最新研究报告 超级AI时代的编程模式可能包括: 脑机接口:通过思维直接传达编程意图。 AR手势交互:在虚拟空间中操控代码组件,如钢铁侠电影中的场景。 多模态融合交互:结合语音、手势、眼动跟踪等多种方式。 自适应自然语言处理:AI能够理解和解析非结构化的自然语言,转换为代码逻辑。 这些技术的发展可能会让未来的编程体验更像是与高度智能的助手协作,而非单纯的工具使用。如今脑机接口、AR增强现界等技术也在快速演进,很可能与超级AI带来的智能时代同时到来。 程序员角色的转变 在超级AI时代,程序员的角色将发生显著的变化。程序员基本上不再编码,而是更多地转变为”系统架构师”、”AI协作者”和”创新推动者”。他们的工作会更多地涉及高层次的问题解决、创新思考和跨学科合作。技术知识仍然重要,但更重要的是理解业务需求、系统设计、伦理考量和用户体验等更广泛的技能。 Sequoia Capital的报告指出,随着AI技术的进步,软件开发正在从”软件即服务”(SaaS, Software as a Service)模式转向”服务即软件(Service as a Software”模式。这意味着AI应用不仅仅是提供软件工具,而是直接提供完整的服务解决方案。这种转变将极大地扩展AI应用的市场,从软件市场扩展到更广阔的服务市场: 来自Sequoia Capital的最新研究报告 注:怎么理解“服务即软件”(Service as a [...]

Go语言演进的双保险:GOEXPERIMENT与GODEBUG

2024-10-11 23:08:35

本文永久链接 – https://tonybai.com/2024/10/11/go-evolution-dual-insurance-goexperiment-godebug Go语言自诞生以来就以其简洁、高效和强大的并发支持而闻名,Go团队承诺保持Go1向后兼容性,以确保用户的代码在未来的版本中继续正常运行。然而,保持语言的稳定性与不断创新(增加新特性)之间的平衡一直是Go团队面临的挑战。为了应对这一挑战,Go语言引入了两个关键机制:GOEXPERIMENT和GODEBUG来平衡新功能的试验、稳定发布和向后兼容。这两个机制共同构成了Go语言特性发布的“双保险”,确保语言能够稳步前进的同时,不会因为激进的改变而影响现有代码的稳定性。本文就来简单探讨一下这两个机制是如何保障Go语言新特性稳定发布的。 1. GOEXPERIMENT:新特性的摇篮 GOEXPERIMENT是一个Go语言的环境变量,是用于控制实验性特性的机制。它允许开发者在编译时(使用go build、go install、go run或go test)启用一些尚未正式发布的语言特性或优化。通过GOEXPERIMENT,Go团队能够在正式发布之前广泛测试新功能,收集反馈并进行必要的调整。 比如,在今年8月发布的Go 1.23版本发布了一个实验特性:带有类型参数的type alias,就像下面代码一样,我们可以在编译时开启该实验特性: // github.com/bigwhite/experiments/blob/master/go1.23-examples/lang/generic_type_alias.go $GOEXPERIMENT=aliastypeparams go build generic_type_alias.go $./generic_type_alias Int Slice: [1 2 3 4 5] String Slice: [hello world] Person Slice: [{Alice 30} {Bob 25}] 如果不开启实验特性,上述的代码就会编译失败: // github.com/bigwhite/experiments/blob/master/go1.23-examples/lang/generic_type_alias.go $go build generic_type_alias.go # command-line-arguments ./generic_type_alias.go:5:6: generic type alias requires GOEXPERIMENT=aliastypeparams 我们看到:通过设置GOEXPERIMENT=featureflag可以开启对应的实验特性,如果要同时开启多个实验特性,可以用逗号分隔的实验特性列表,就像下面这样: $GOEXPERIMENT=featureflag1,featureflag2,...,featureflagN go [...]

代码提交者的代码评审通关指南[译]

2024-10-11 06:13:00

本文永久链接 – https://tonybai.com/2024/10/11/the-cl-author-guide-to-getting-through-code-review Google在软件工程领域对IT界做出了卓越的贡献,从《Google软件工程》,到Google Style Guides,再到The Change Author’s Guide。这些实践参考不仅提升了软件工程的标准,也为全球IT行业的发展提供了宝贵的资源和指导。由于Go是Google开源的,其cl review基本上是遵循了Google内部的标准和实践,可以帮助开发人员更快地完成审核并获得更高质量的结果。因此在这篇文章中,我翻译一下The Change Author’s Guide,供大家参考。 The Change Author’s Guide分为三部分,由于每一部分篇幅都不多,这里就放在一起了。本次翻译是基于Google Engineering Practices Documentation的commit 3bb3ec25b3b0199f4940b1aa75f0ac5c5753301c进行的。 注:Google内部使用的术语CL代表“变更列表(changelist)”,指的是一个自包含的更改,该更改已经提交到版本控制系统或正在进行代码评审。其他组织通常称之为“变更”、“补丁”或“拉取请求(PR)”。 1. 编写良好的CL描述 CL描述是变更的公开记录,重要的是它能够传达以下信息: 做了什么 变更?这应该总结主要的变化,使读者在不需要阅读整个CL的情况下了解正在发生的变化。 为什么要做出这些变更?作为作者,你在做出这个变更时有什么背景?以及你做出的那些在源代码中无法反映出来的决策?等等。 CL描述将成为我们版本控制历史的一部分,未来可能会被数百人阅读。 未来的开发人员将根据描述搜索你的CL。未来某人可能因为对其相关性有模糊的记忆而寻找你的变更,但没有具体细节。如果所有重要信息都在代码中而非描述中,他们将更难找到你的CL。 而且,在他们找到CL后,是否能够理解为什么做出这个变更?阅读源代码可能会揭示软件在做什么,但可能不会揭示其存在的原因,这可能会使未来的开发人员更难知道他们是否可以移动切斯特顿的栅栏(Chesterton’s fence)。 译注:切斯特顿的栅栏是一种启发式方法,由G.K.切斯特顿提出,旨在告诫人们在改变任何系统之前,应先了解该系统存在的原因和功能,否则可能会造成更大的问题。 一个编写良好的CL描述将帮助这些未来的工程师——有时,也包括你自己! 1.1 第一行(first line) 简短总结所做的内容。 使用完整句子,以命令的形式书写。 后面跟一个空行。 CL描述的第一行应该是对具体做了什么的简短总结,后面跟一个空行。这是出现在版本控制历史摘要中的内容,因此应该提供足够的信息,使未来的代码搜索者无需阅读你的CL或其整个描述就能理解你的CL实际上做了什么,或与其他CL的不同之处。也就是说,第一行应该独立存在,让读者更快地浏览代码历史。 尽量保持第一行简短、重点突出且切中要点。清晰性和对读者的实用性应是最重要的。 按照传统,CL描述的第一行应该是一个完整的句子,并以命令形式书写(即祈使句)。例如,应该说“Delete the FizzBuzz RPC and replace it with the new system.”,而不是“Deleting the FizzBuzz [...]

Go语言的新时代:新领导团队和未来规划

2024-10-10 08:06:33

本文永久链接 – https://tonybai.com/2024/10/10/pass-torch-to-go-new-leadership-team 在最近一期的GoTime播客“Russ Cox on passing the torch”中,主持人Angelica Hill邀请了Go团队的三个核心角色:前任Tech Leader Russ Cox与现任Tech Leader Austin Clements以及Go运行时和编译器的技术负责人Cherry Mui,一起讨论了Go的领导层交接以及对Go未来的规划。 在播客中,这三人组成的Go的技术领导团队讨论了其内部的重要变动。担任Go技术负责人超过十年的Russ Cox正式卸任,将权杖交给了新的Go技术负责人Austin Clements。同时,Cherry Mui接任Austin之前的职位,成为Go运行时和编译器(也称Go core)的技术负责人。这些领导层变动标志着Go项目发展的一个重要时刻,Austin和Cherry都为各自的角色带来了新的视角,而Russ则转向探索人工智能和软件维护交叉领域的全新角色,继续为团队提供支持。 Russ Cox:回顾12年的领导之路 Russ Cox自2008年起参与Go项目,并于2012年成为其技术负责人。Russ分享了他卸任的想法,对他来说,这一决定是顺其自然的发展。他强调,定期更换领导者至关重要,这有助于引入新思想并防止项目陷入停滞。Russ很早就招募了Austin,因为两人对Go 共享相似的愿景,领导权的交接也进行得十分顺利,Russ仍将继续提供支持。 在他的新角色中,Russ将专注于利用人工智能来简化软件维护工作。他相信,特别是大语言模型,可以帮助自动化诸如问题分类和重复问题检测等耗时的任务。这项探索是一个更广泛的尝试,旨在减少维护人员的工作负担,并提高项目管理的整体效率。 Austin Clements:稳定与增长的愿景 加入Go团队已有十多年的Austin Clements担任新技术负责人,致力于保持Go的稳定性。Austin强调,虽然Go保持着稳定和简洁,但它也必须继续演进。他的首要目标之一是改善Go的可扩展性——无论是在Go的开发过程中,还是在背后的工程流程中。 Austin还希望通过提高透明度和扩大社区参与度,赋能社区。他希望创建能够更好地整合用户反馈的平台(可能是一个Forum),使贡献者能够开发与核心团队目标一致的工具和解决方案。 在性能改进方面,Austin长期致力于优化Go的垃圾回收系统。他目前正在试验一种新算法,幽默地称其为“绿茶”,旨在优化资源使用,进一步推动Go在越来越大的系统上扩展的能力。 Cherry Mui:应对核心扩展性挑战 作为Go运行时和编译器的新技术负责人,Cherry Mui自2016年加入Go团队以来,主要专注于解决与人和机器扩展性相关的问题。Cherry是一个巾帼,为人十分低调,这次GoTime播客第一次贴出了她的照片,根据她的自我介绍,她来自布朗大学化学系,机缘巧合加入了Go团队。从Cherry的声音来看,她是一个“女汉子”,但又与照片的形象不太一致:)。从Cherry的口音来看,她似乎不是土生土长的美国人。 在播客中,Cherry认为,Go的用户基础在快速增长,而核心团队的资源却有限。她的任务是确保Go平台能够支持这一日益增长的社区,无论是通过构建更好的API还是平台,帮助用户在Go的基础上构建更强大的工具和解决方案。 在技术扩展性方面,Cherry也提出了自己的关注点。随着机器变得越来越强大,核心数量和内存容量不断增加,Go需要适应以高效地处理更大的工作负载。Cherry表示,她很期待与社区中的工程师合作,解决这些挑战,保持Go简单且可扩展的声誉。 展望未来:Go的新方向 Austin和Cherry都对各自的新角色和塑造Go未来的机会感到兴奋。尽管他们都不打算对Go语言进行彻底变革,但他们承诺将继续解决Go社区的不断演变需求,并保持其核心理念的稳定性和简洁性。 随着Russ Cox现在专注于人工智能在软件维护中的应用,Austin致力于推动社区参与和技术扩展,Cherry聚焦核心基础设施的改进,Go 项目正进入一个全新的时代。这次过渡不仅仅是领导层的更替,更是一种重新焕发活力的感觉,随着Go团队继续保持其初衷,项目也将在新的领导下迎来新的发展阶段:一个充满技术创新和社区互动的时代。Go社区可以期待在Austin和Cherry带来的新视角引导下,Go项目将会迎来一个更加稳健的发展时期,同时也保持着Russ长期积累的智慧和支持。 Gopher部落知识星球在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时,我们也会加强代码质量和最佳实践的分享,包括如何编写简洁、可读、可测试的Go代码。此外,我们还会加强星友之间的交流和互动。欢迎大家踊跃提问,分享心得,讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落,享受coding的快乐! 欢迎大家踊跃加入! 著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。 Gopher Daily(Gopher每日新闻) – https://gopherdaily.tonybai.com [...]

与Thorsten Ball的共鸣:Go作为教学语言在技术写作中的优越性

2024-10-09 06:14:22

本文永久链接 – https://tonybai.com/2024/10/09/resonating-with-thorsten-ball-on-go-in-technical-writing 近日,两本备受好评的畅销书《用Go语言自制解释器(Writing An Interpreter In Go)》和《用Go语言自制编译器(Writing A Compiler In Go)》的作者、前Sourcegraph工程师索斯藤·鲍尔(Thorsten Ball)发表了一篇名为“Glad I did it in Go”的文章。在这篇文章中,Thorsten表达了他对8年前编写这两本书时选择Go语言作为教学语言的庆幸之情。 2021年12月17日,我的第一本Go技术图书《Go语言精进之路vol1和vol2》出版了,至今好像是已经是第4次重印了(修正了勘误表中的所有瑕疵)。作为该书作者,当我读到Thorsten Ball的这篇回顾文章时,我感到了一种强烈的共鸣,其中的许多观点与我的不谋而合。尽管我们的书主题不同,但我们都体会到了选择Go语言作为教学语言进行技术写作的巨大优势。 在这篇文章中,在《Go语言精进之路》出版即将三年之际,我想借此机会分享我的thoughts,探讨Go语言如何为技术作者提供了独特的优势。 1. Go的稳定性和向后兼容性 首当其冲的优势就是Go的稳定性和向后兼容性,它们给我留下了深刻的印象。三年快过去了,当初《Go语言精进之路》中使用Go 1.16版本编写的代码示例,在最新的Go 1.23版本中仍然可以完美运行,几乎不需要任何修改。这种稳定性不仅让我的书保持了长期的相关性,也让读者能够轻松地在不同版本的Go环境中实践书中的内容。正如Thorsten所提到的,他只需添加一个简单的go.mod文件,就能使8年前的代码适应新的Go版本依赖管理和构建模式,这种对更新需求的最小化,在快速发展的编程语言世界中,实属难能可贵。 Go的稳定性还体现在语法特性上,《Go语言精进之路》一书中讲解的语法和惯用法在今天依然是完全有效的,除了loopvar的语义变更可能会让极少的内容略显“过时”。Thorsten也提到了这种稳定性的好处:8年前的代码运行golangci-lint得到的警告与当时是相同的(便于读者复现书中的情形),其书中代码风格仍然符合现在的Go惯例写法。 此外,Thorsten还提及了Go工具链和标准库的稳定性:8年来Go的工具链几乎没有变化,新手容易上手。像Thorsten一样,我也发现Go的开发环境和工具在多年来保持了惊人的一致性。这意味着书中介绍的开发实践和工具使用方法始终有效,大大降低了内容过时的风险。对技术作者来说,这种稳定性是无价的,它允许我们专注于概念和最佳实践,而不是不断更新工具相关的内容。 以上Go的这些稳定性和向后兼容,让我的书中的内容具有了更为持久的生命力,书中内容的价值变得更为长效,也大大减轻了作者对书籍维护和更新的负担,在技术书籍的生命周期中,这一点尤为宝贵。 2. Go的简洁性和可读性 其次,在编写《Go语言精进之路》时,我发现Go的简洁性和可读性为技术写作带来了极大的帮助。许多读者反馈说,即使他们之前没有Go的经验,也能快速上手并理解书中的概念。这种简洁和直观性让Go也成为了编写教程和教学材料的理想选择。此外,正如在项目中所经历的那样,Thorsten也强调了Go语言的语法简单直观在教学过程中的所展现的优势,它既能让初学者快速入门,也能使得书中关于解析器和编译器实现的核心思路能够被清晰地传达给读者,即便在探讨复杂的概念时,也能保持清晰明了。 同时,Thorsten强调内置的gofmt带来的通用风格和测试框架也简化了学习过程,让读者可以专注于理解核心概念和解释器/编译器的实现,而不是纠结于环境设置和代码风格。 3. Go代码易于理解和翻译 Thorsten提到许多读者在从未写过Go代码的前提下,能够将他的Go代码轻松翻译成其他语言,这体现了Go在跨语言学习和理解方面的优势,有利于扩大了书籍的受众群体,而不仅限于Go开发者。Go社区的多样性和活跃度也为此做出了重要贡献,各种语言背景的开发者都能在Go中找到共鸣。这种跨语言的适应性不仅拓展了书籍的应用范围,也增强了其教育价值。 4. 小结 回顾这三年,我与Thorsten一样,越发感慨选择Go作为教学语言进行技术写作是多么明智的决定。当然,我这本书本身就是围绕Go语言展开的^_^,这与Thorsten的书籍主题有所不同。Thorsten在8年前高瞻远瞩地选择Go,才着实令人钦佩,要知道那时的Go刚刚发布1.6版本。Go语言不仅是一个强大的编程工具,更是技术作者的得力助手。它的稳定性、简洁性、易理解性和良好的翻译能力,以及稳定优秀的工具链,为我们创造高质量、长寿命的技术内容提供了坚实的基础。 与Thorsten Ball一样,我也为选择Go感到庆幸。看到自己的作品能够持续为读者提供价值,这种成就感是无可比拟的。Go语言在技术写作中展现出的优越性,不仅使我们的书籍能够经受时间的考验,还为整个技术写作领域树立了新的参考标杆。 展望未来,我相信Go语言将继续是技术作者的优秀选择。它不仅是一种编程语言,更是连接作者、读者与技术的桥梁。 Gopher部落知识星球在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时,我们也会加强代码质量和最佳实践的分享,包括如何编写简洁、可读、可测试的Go代码。此外,我们还会加强星友之间的交流和互动。欢迎大家踊跃提问,分享心得,讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落,享受coding的快乐! 欢迎大家踊跃加入! 著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。 Gopher Daily(Gopher每日新闻) – https://gopherdaily.tonybai.com 我的联系方式: 微博(暂不可用):https://weibo.com/bigwhite20xx 微博2:https://weibo.com/u/6484441286 [...]

从DevOps到日常脚本:聊聊Go语言的多面性

2024-10-08 06:46:09

本文永久链接 – https://tonybai.com/2024/10/08/go-languages-versatility-from-devops-to-daily-scripts 2024年初,TIOBE编程语言排行榜上,Go再次进入了前十,并在之后又成功冲高至第七名。 Go语言的排名上升,至少在Reddit Go论坛上帖子数量和在线人数上得到了体现,尽管目前与Rust热度仍有差距,但可见Go的关注度在提升: 2024年国庆节假期某天下午的实时在线数对比 随着Go语言人气的上升,论坛中的问题也变得愈发多样化。许多Gopher常常问及为何Go是DevOps语言和Go适合用作脚本语言吗等问题,这些都反映了Go语言的多面性。 从最初的系统编程语言,到如今在DevOps领域的广泛应用,再到一些场合被探索用作脚本语言,Go展现出了令人惊叹的灵活性和适应性。在本篇文章中,我们将聚焦于Go语言在DevOps领域的应用以及它作为脚本替代语言的潜力,聊聊其强大多面性如何满足这些特定场景的需求。 1. Go在DevOps中的优势 随着DevOps的发展,平台工程(Platform Engineering)这一新兴概念逐渐兴起。在自动化任务、微服务部署和系统管理中,编程语言的作用变得愈发重要。Go语言凭借其高性能、并发处理能力以及能够编译成单一二进制文件的特点,越来越受到DevOps领域开发人员的青睐,成为开发DevOps工具链的重要组成部分。 首先,Go的跨平台编译能力使得DevOps团队可以在一个平台上编译,然后在多个不同的操作系统和架构上运行,结合编译出的单一可执行文件的能力,大大简化了部署流程,这也是很多Go开发者认为Go适合DevOps的第一优势: $GOOS=linux GOARCH=amd64 go build -o myapp-linux-amd64 main.go $GOOS=linux GOARCH=arm64 go build -o myapp-linux-arm64 main.go $GOOS=darwin GOARCH=amd64 go build -o myapp-darwin-amd64 main.go $GOOS=windows GOARCH=amd64 go build -o myapp-windows-amd64.exe main.go 其次,Go的标准库仿佛“瑞士军刀”,开箱即用,为DevOps场景提供了所需的丰富的网络、加密和系统操作功能库,大幅降低对外部的依赖,即便不使用第三方包生态系统,也可以满足大部分的DevOps功能需求。 此外,Go的goroutines和channels为处理高并发任务提供了极大便利,这在DevOps中也尤为重要。例如,以下代码展示了如何使用goroutines并发检查多个服务的健康状态: func checkServices(services []string) { var wg sync.WaitGroup for _, service := [...]

Go项目中使用Git Submodule,还有这个必要吗?

2024-10-05 18:24:23

本文永久链接 – https://tonybai.com/2024/10/05/using-git-submodules-in-go-projects 在软件开发中,依赖管理一直是一个重要的议题,特别是在像Go这样的编程语言中,随着项目的扩展,如何有效管理依赖变得至关重要。Git Submodule作为Git的一个重要功能,允许在一个Git仓库中嵌入另一个仓库,从而方便地管理跨项目的代码共享。然而,Go语言引入的Go Module机制似乎已经解决了依赖管理的问题,那么在Go项目中,是否还有使用Git Submodule的必要呢?本文将简单探讨一下Go项目中Git Submodule的使用方法,并分析它是否还值得使用。 1. Git Submodule是什么? Git Submodule是Git版本管理工具提供的一个功能,允许你将一个Git仓库作为另一个Git仓库(主仓库)的子目录。主仓库通过记录Submodule的URL和commit hash来追踪Submodule。当你克隆一个包含Submodule的仓库时,需要额外的步骤来初始化和更新Submodule。 下面是一个将github.com/rsc/pdf仓库作为git submodule的示例。 我们先建立主仓库: $mkdir main-project $cd main-project $go mod init main-project $git init $git add -A $git commit -m"initial import" . [master (root-commit) 8227e65] initial import 1 file changed, 3 insertions(+) create mode 100644 go.mod 接下来,我们来添加submodule: $git submodule add https://github.com/rsc/pdf.git Cloning [...]

探索Go守护进程的实现方法

2024-10-03 21:41:55

本文永久链接 – https://tonybai.com/2024/10/03/how-to-daemonize-go-program 在后端开发的世界里,守护进程(daemon)这个概念与Unix系统一样古老。守护进程是在后台运行的长期服务程序,不与任何终端关联。尽管现代进程管理工具如systemd和supervisor等让应用转化为守护进程变得十分简单,我们甚至可以使用以下命令来在后台运行程序: nohup ./your_go_program & 但在某些情况下,程序的原生转化为守护进程的能力仍然是有必要的。比如分布式文件系统juicefs cli的mount子命令,它就支持以-d选项启动,并以守护进程方式运行: $juicefs mount -h NAME: juicefs mount - Mount a volume USAGE: juicefs mount [command options] META-URL MOUNTPOINT ... ... OPTIONS: -d, --background run in background (default: false) ... ... ... ... 这种自我守护化的能力会让很多Go程序受益,在这一篇文章中,我们就来探索一下Go应用转化为守护进程的实现方法。 1. 标准的守护进程转化方法 W.Richard Stevens的经典著作《UNIX环境高级编程》中对将程序转化为一个守护进程的 (daemonize) 步骤进行了详细的说明,主要步骤如下: 创建子进程并终止父进程 通过fork()系统调用创建子进程,父进程立即终止,保证子进程不是控制终端的会话组首领。 创建新的会话 子进程调用setsid()来创建一个新会话,成为会话组首领,从而摆脱控制终端和进程组。 更改工作目录 使用chdir(“/”) 将当前工作目录更改为根目录,避免守护进程持有任何工作目录的引用,防止对文件系统卸载的阻止。 重设文件权限掩码 [...]

为什么Canonical Import Path注释在Go中不再必要

2024-10-02 21:04:59

本文永久链接 – https://tonybai.com/2024/10/02/why-canonical-import-paths-no-longer-necessary-in-go Go语言自推出以来,一直以其简洁和高效的包管理系统著称。在Go 1.11版本之前,Canonical Import Path注释曾是一个重要的工具,用于防止包路径的导入冲突。然而,随着Go Modules的引入,这一工具的作用逐渐被淡化。那么Canonical Import Path注释是否还有必要存在呢?在这篇文章中,我就来介绍一下Canonical Import Path的历史及作用,并通过在Go Modules环境下的向后兼容性测试,讨论是否仍有必要继续使用这一注释。 1. 什么是Canonical Import Path注释? Go在1.4版本中增加了Canonical Import Path,Canonical Import Path用于解决同一个包可能被通过多个导入路径导入的问题。比如当代码托管在像github.com这样的服务上时,导入路径会包含托管服务的域名,比如“github.com/rsc/pdf。但是Go开发者也可以为同一个包提供一个“自定义”或“vanity”导入路径,例如rsc.io/pdf。这样就会产生两个有效的导入路径,这会带来以下问题: 同一个程序中可能会通过不同路径导入同一个包,造成不必要的重复。 使用非官方路径时可能会错过包更新,因为路径没有得到正确识别。 将包迁移到另一个托管服务时,可能会中断使用旧路径的客户端。 为了解决这个问题,Go 1.4引入了Canonical Import Path注释。在包声明中加上注释后,如果通过非Canonical Import Path导入包,Go命令将拒绝编译导入包的程序。 Canonical Import Path的语法很简单,在包声明的注释部分加上标识。例如,对于rsc.io/pdf包,声明可以写成: package pdf // import "rsc.io/pdf" 这样,Go命令就会拒绝编译任何通过github.com/rsc/pdf路径导入的包,确保代码可以在不破坏用户代码的前提下自由迁移。 2. Go Modules及其对导入路径的影响 Go 1.11引入Go Modules后,Go通过go.mod文件管理包的依赖关系和版本,极大简化了包的管理过程。通过在go.mod中定义模块的根路径,Go Modules可以自动指示项目中所有包的导入路径,并且是唯一的,这使得Canonical Import Path在Go Modules环境下基本没什么必要性了。 例如,假设go.mod文件定义了以下模块路径: // go.mod module rsc.io/pdf [...]

跟上Go演进步伐,你只需要关注这几件事儿

2024-09-30 20:46:55

本文永久链接 – https://tonybai.com/2024/09/30/how-to-keep-up-with-go-evolution Go语言以其简洁、高效和强大的特性赢得了众多开发者的青睐。与许多主流编程语言有着明确的演进Roadmap或下一个版本spec不同,Go的演进过程更加独特、灵活与开放。这种看起来不那么正式和严肃的演进方式却也能让Go快速响应开发者的需求,同时保持语言的稳定性和一致性。 作为一名Go开发者,跟上Go的演进步伐,甚至是参与到这个激动人心的过程中来,不仅能让你更好地利用语言的新特性,还能帮助你更深入地理解Go的设计哲学。 但很多Go开发者只知道每年Go有两次的大版本Release,并通过大版本的Release Notes来了解Go的演进。这无可厚非,但对于那些想及时跟进Go演进的Gopher来说,光有一年两次的Release Notes还是不够的的,很难及时跟进Go的演进决策。 但如果直接到Go语言项目的issue中去翻阅,面对Go丰富的社区讨论和频繁的更新,你可能会感到无从下手。别担心,本文将为你指明方向,让你只需关注几个关键点,就能轻松跟上Go的演进步伐。 1. 开发计划早知道 Go的版本规划具有很高的灵活性。每个Go 1.x版本在开发前,Go语言项目相关人员都会在golang-dev讨论组上发布一个帖子,这个帖子通常的标题为”Planning Go 1.x”,例如”Planning Go 1.23″,如下图: 很多contributor,无论是Go团队的,还是外部贡献者的,会在该帖子下面留下自己的plan(注意:这些plan中的特性可不一定会在最终的版本中发布),然后等main tree开放后,就会将已经准备完毕的cl(changelist) merge到main tree中去,或开始提交cl,等待Go团队或社区的开发者进行评审。 当然对于Go 1.x这样的大版本,Go团队会在github建立专门的milestone跟踪,大家也可以在对应的milestone中看到该版本带来的新特性等,下图是目前正在积极开发的Go 1.24版本里程碑: 通过查看这些Plan或定期查看Go 1.x里程碑,你可以提前了解Go的发展方向,为新版本的到来做好准备。 当然如果要了解那些更早的Go演进的决策,我们还得关注和跟踪下面的Proposal Project看板和三个关键的issue。 2. Proposal Project看板和三个关键的Issue Go在早期并没有规范的proposal提案流程,更多是由Rob Pike、Robert Griesemer等三个Go语言之父,外加Ian Taylor和Russ Cox讨论确定,这一状态在Russ Cox建立明确的Go proposal提案流程后结束,提案流程是Go团队审查提案并决定接受或拒绝提案的过程。Russ Cox在提案流程中明确了Go项目的开发过程是设计驱动(design-driven)的,必须首先对语言、库或工具的重大更改进行讨论(包括Go语言项目主仓库和所有golang.org/x仓库中的API更改,以及对go command的命令行更改),并在实现这些设计之前进行正式记录。 Go团队目前使用Proposal Project看板和GitHub Issues来追踪语言的演进,下面我们来看看这个看板和值得关注的三个Issue。 2.1 Proposal Project看板 Proposal Project看板是Go团队跟踪proposal的全局视图,当然要理解该看板,我们需要先来简单看看Go的proposal流程以及每个提案的生命周期是怎样的。 Go Proposal流程并不复杂,可以概括为下面这个示意图: 该流程图展示了Go提案流程的几个主要步骤: 任何人都可以作为提案作者,在Go项目上创建一个简短的issue来描述提案。 Go团队成员以及任何Go社区成员在issue上进行初步讨论,由一组人组成的Go提案审核委员会决定是接受提案、拒绝提案,还是需要进一步的设计文档。 如果需要进一步的设计文档,提案作者会撰写一个详细的设计文档。 在设计文档的评论减少/收敛后(意见趋于一致后),由Go提案审核委员会会进行最终讨论,决定接受或拒绝提案。 [...]