关于 TonyBai | 白明

《Go语言精进之路》作者,Go C程序员,架构师,技术讲师、撰稿人。先后贡献了lcut、cbehave、buildc多个工具框架。

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

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

TonyBai | 白明 RSS 预览

Go unique包:突破字符串局限的通用值Interning技术实现

2024-09-18 06:06:19

本文永久链接 – https://tonybai.com/2024/09/18/understand-go-unique-package-by-example Go的1.23版本中引入了一个新的标准库包unique,为Go开发者带来了高效的值interning能力。这种能力不仅适用于字符串类型值,还可应用于任何可比较(comparable)类型的值。 本文将简要探讨interning技术及其在Go中的实现方式,通过介绍unique包的功能,帮助读者更好地理解这一技术及其实际应用。 1. 从string interning技术说起 通常提到interning技术时,指的是传统的字符串驻留(string interning)技术。它是一种优化方法,旨在减少程序中重复字符串的内存占用,并提高字符串比较操作的效率。其基本原理是将相同的字符串值在内存中只存储一次,所有对该字符串的引用都指向同一内存地址,而不是为每个相同字符串创建单独的副本。下图展示了使用和不使用string interning技术的对比: 这个图直观地展示了string interning如何通过共享相同的字符串来节省内存和提高效率。我们看到:在不使用string interning的情况下,每个字符串都有自己的内存分配,即使内容相同,比如”Hello”字符串出现两次,占用了两块不同的内存空间。而在使用string interning的情况下,相同内容的字符串只存储一次,比如:两个”Hello”字符串引用指向同一个内存位置。 string interning在多种场景下非常有用,比如在解析文本格式(如XML、JSON)时,interning能高效处理标签名称经常重复的问题;在编译器或解释器的实现时,interning能够减少符号表中的重复项等。 传统的string interning通常使用哈希表或字典来存储字符串的唯一实例。每次出现新字符串时,程序首先会检查哈希表中是否已有相同的字符串,若存在则返回其引用,若不存在则将其存储在表中。 Michael Knyszek在Go官博介绍interning技术时,也给出了一个传统实现的代码片段: var internPool map[string]string // Intern returns a string that is equal to s but that may share storage with // a string previously passed to Intern. func Intern(s string) string { pooled, ok := [...]

JSON包新提案:用“omitzero”解决编码中的空值困局

2024-09-12 07:55:56

本文永久链接 – https://tonybai.com/2024/09/12/solve-the-empty-value-dilemma-in-json-encoding-with-omitzero Go标准库是Go号称“开箱即用”的重要因素,而标准库中的encoding/json包又是标准库最常用的Go包。虽然其性能不是最好的,但好在由Go团队维护,对JSON规范兼容性好,且质量很高。但json包也不是没有“瑕疵”的,Go官方继math/rand/v2之后,也开启了encoding/json/v2的讨论,v2包含了对功能的增强,其中就包含了对空值编码的改进的考量,以及性能方面的优化。但json/v2毕竟还属于“长远”规划,当前版本的json包的问题也要修正和完善。 一个提出于2021年的issue近期被即将“功成身退”的Russ Cox接受(accept),该issue就当前json包对空值编码的“瑕疵”做了描述并提出了修正方案。本文就将针对这一问题以及其方案进行探讨,希望能帮助大家更好地理解该issue以及其对应的方案。 1. 问题溯源:omitempty的局限性 在encoding/json包中,omitempty标签是开发者控制JSON序列化行为的重要工具。它的设计初衷是允许开发者指定:当某个字段值为“空”时,在JSON编码过程中应该被忽略。然而,omitempty的空值定义存在一些固有的局限性。下面是json包中对omitempty的说明: The “omitempty” option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string. 总结一下,omitempty标签的判断逻辑如下: 对于布尔类型:false被视为空 对于数值类型:0被视为空 对于字符串:”"(空字符串)被视为空 对于指针、接口:nil被视为空 对于数组、切片、map:长度为0被视为空 下面是一个完整的Go示例,展示了omitempty标签在不同类型上的应用: [...]

致敬:程序员成长路上的良师与经典著作

2024-09-10 21:14:07

本文永久链接 – https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works 早上送孩子去幼儿园的路上,收到一个小伙伴的微信: 我这才意识到今天是教师节!为人师,自觉还不够格!但在这个特殊的日子,作为IT行业从业人员,我想向那些在计算机科学和编程领域给予我们启迪的“老师们”致敬。这些老师可能不是传统意义上站在讲台前的教育者,但他们通过自己的著作、思想和贡献,通过他们的智慧结晶,为我们指明了方向,为无数程序员的成长之路点亮了明灯。 这里我列举的作者与其著作也都是我个人从大学开始至今在计算机编程学习和实践之路上受到深刻影响的重要参考资料。这些书籍不仅丰富了我的知识,也激发了我对编程的热情和探索精神。每一位作者的独特视角和深入浅出的讲解,都让我在理解复杂概念时受益匪浅。希望也能引起大家的共鸣。 注:计算机领域巨匠甚多,笔者见识有限,不能一一列举,这里仅列出我亲自读过且对我影响深远的作者及其代表作品,至于像唐纳德·克努斯和他的巨著《计算机程序设计艺术》等,由于我并未拜读过,这里也就没有列出。 注:书中的图书封面图片可能并非该书最新版的封面,而是笔者购买时的版本的封面图片。 2. 编程语言 2.1 C语言/Go语言领域 2.1.1 Dennis Ritchie 大一的时候学校开设了C语言编程课,指定谭浩强老师的《C程序设计(第二版)》作为随课教材,当时我特意到大学书店花了银子买了本,并奉为皋臬。 直到我看到清华出版的影印版《C程序设计语言(第二版)》,才发现自己天真了,这本才是真正的“圣经”! Dennis Ritchie,被誉为”C语言之父”,1983年图灵奖得主(与Ken Thompson同年获得)。他不仅创造了C语言,还与Ken Thompson一起开发了UNIX操作系统。刚刚过去的9月9日是其诞辰纪念日,MIT CSAIL在X上发文纪念了这位计算机先驱和现代编程语言奠基人: 他与Brian Kernighan合著的《The C Programming Language》被亲切地称为“K&R C”,是学习C语言的必读经典,书籍不厚,它以简洁明了的语言介绍了C语言的核心概念(遵循当时的ANSI C89/C90标准),影响了几代程序员。 2.1.2 Brian Kernighan 说完K&R中的R,我们再来说K。K指的是Brian Kernighan,他也是Bell实验室UNIX开发团队的重要成员,是C语言的主要推广者之一,他也是AWK语言中的最后的那个K。和Dennis Ritchie等动不动就是语言之父不同,Kernighan以写作风格闻名。他的写作风格清晰易懂,使复杂的概念变得平易近人,并以一种易于理解和应用的方式呈现给读者。这使得与Dennis Ritchie合著的《C程序设计语言》不仅是C语言语言特性的权威指南,更是编程语言类书籍技术写作的典范,之后很多编程语言类的书籍都参考Kernighan的风格,至少也会先从一个“Hello, World”开始全书的讲解。 其与P.J.Plauger合著的《The Elements of Programming Style》也是程序员眼中的经典。 2015年,已经70高龄的Kernighan又和Go团队的Alan Donovan合著了Go语言编程书籍领域公认的圣经《The Go Programming Language》。这本书与K&R C的风格很相似,作者们以清晰简洁的语言,系统且全面地介绍了Go的语法特性和编程理念,并通过大量的实例展示了Go在实际项目中的应用。书中不仅覆盖了基础知识,还深入探讨了并发编程、unsafe编程等Go高级主题。 2.2 C++ 2.2.1 Bjarne Stroustrup Bjarne Stroustrup是C++语言之父,他从1979年开始,在C语言的基础上添加了面向对象编程等特性,从而创造了C++这门强大而灵活的通用编程语言。C++经过ISO标准化后,他也是C++标准委员会的创始成员,并从那时起一直是一名活跃成员。如今,他还担任负责处理语言扩展提案的小组(进化工作组)的主席。 [...]

重拾精髓:go doc -http让离线包文档浏览更便捷

2024-09-06 06:03:55

本文永久链接 – https://tonybai.com/2024/09/06/go-doc-add-http-support Go语言团队近期接受了Go团队成员、Go圣经《The Go Programming Language》合著者Alan Donovan的新提案,旨在进一步提升开发者体验。这个提案为go doc命令新增了一个强大的功能:通过go doc -http,开发者可以快速启动一个本地的文档服务器,并自动在浏览器中打开Go包的参考文档。该功能为开发者提供了类似pkg.go.dev的离线文档展示形式,同时增强了查看本地文档的交叉引用功能。看到这个提案功能,屏幕前的资深Gopher是不是感觉似曾相识呢:)。 早在去年,我就写过一篇有关go包文档查看方式对比的文章《聊聊godoc、go doc与pkgsite》,在那篇文章中,我就对当前Go包文档查看的几种方式做了详细说明,如果你是Go初学者,不妨点击链接移步过去仔细阅读一番。当然,这里也会简单地再介绍一下Go包文档离线查看工具的演进。 Go语言的包文档查看工具经历了三个重要阶段的演进,分别是godoc、go doc和pkgsite。以下是这些工具的发展历程: godoc是Go语言最早用于查看包文档的工具。它支持通过命令行查看文档,也可以通过-http参数启动一个本地文档服务器,用户在浏览器中以网页形式查看文档。这个工具提供了较为完整的Go包文档浏览体验,支持交叉引用和导航。但随着Go的发展,逐渐不再是官方推荐的工具,并且不再随Go安装包一并发布了! 随着Go的升级与演进,go doc逐渐取代了godoc成为查看包文档的主要工具。go doc主要提供了通过命令行输出包详细文档的能力,对应简单的包查询,这种方式更为高效: $go doc -h Usage of [go] doc: go doc go doc <pkg> go doc <sym>[.<methodOrField>] go doc [<pkg>.]<sym>[.<methodOrField>] go doc [<pkg>.][<sym>.]<methodOrField> go doc <pkg> <sym>[.<methodOrField>] For more information run go help doc Flags: -C dir change [...]

Go 1.18之后的语法新特性Quiz,你能做对几个?

2024-08-27 18:55:33

本文永久链接 – https://tonybai.com/2024/08/27/a-new-syntax-quiz-after-go-1-18 自Go 1.18版本以来,Go语言引入了许多令人兴奋,但也可能令你感觉难以理解的语法新特性。这些特性大大增强了语言的表达能力,但也增加了学习曲线。今天,我们通过几个小Quiz来测试你对这些新特性的理解。准备好挑战自己了吗?答案在文章末尾公布,但请先尝试独立思考每个问题! 注:为了保证答案一致,这里的答案输出都是基于刚发布没多久的Go 1.23.0版本。 Quiz 1: 泛型与类型集合(Go 1.18) import ( "fmt" "golang.org/x/exp/constraints" ) type Scalar interface { constraints.Integer | constraints.Float | ~string } func Plus[T Scalar](a, b T) T { return a + b } type MyString string func main() { fmt.Println(Plus(1, 2)) fmt.Println(Plus(1.5, 2.7)) fmt.Println(Plus("Hello, ", "World")) fmt.Println(Plus(MyString("Go "), MyString("1.18+"))) } [...]

从零开始编程:Go语言真的适合新手吗?

2024-08-22 06:03:23

本文永久链接 – https://tonybai.com/2024/08/22/go-as-first-language Go语言自诞生以来,一直以其简洁、高效和面向工程的特性受到开发者的青睐,尤其是在后端开发和并发编程方面,Go表现出了独特的优势。然而,作为一门以简单著称的语言,它是否适合作为编程初学者的第一门语言呢?笔者今天在Reddit上看到有人提出此类问题,也做了一些思考,这里就通过本文从多个角度来和大家一起探讨下这一问题。 我们先从Go适合作为第一门语言的特质说起。 1. Go语言的简洁性 在我的《Go语言精进之路第一卷》第3节“理解Go语言的设计哲学”中我就提到过:Go语言的设计哲学是“做减法”,拒绝走语言特性融合的道路,提供简单的用户界面,将复杂性留给语言自身的设计和实现者。 这种简洁性让初学者能够更快地上手,将精力聚焦在理解编程的基本概念和程序的逻辑结构上,而不是被复杂的语法规则所困扰。例如,Go的语法简洁明了,没有太多冗余的语法糖(一个事情大多只有一种写法),使得代码更容易阅读、理解和维护。 此外,Go的静态类型系统提供了清晰的类型检查机制,这有助于初学者理解变量和类型的概念。与动态类型语言相比,Go的类型系统减少了初学者在学习过程中可能遇到的困惑。此外,Go仍保留了指针等底层概念,让学生在学习过程中还能够接触到内存管理和效率优化的基础知识,也便于学习数据结构与算法,为后续的进阶学习做好铺垫。 2. 并发编程的天然优势 随着多核处理器的普及,并发编程已经成为现代编程的重要技能。Go语言将并发编程作为核心特性,通过goroutines和channels提供了一种简洁直观的并发模型。相比于传统的线程管理,Go的并发模型更加易于理解和使用,这为初学者在学习并发编程时提供了极大的便利。 通过学习Go的并发编程模型,初学者能够及早掌握现代编程中的关键概念,为后续在各种领域的发展打下坚实的基础。 3. 学习曲线与实践应用 经过Go团队不懈的努力,Go语言的安装与使用过程已经非常简单明了了,可以说开箱即用,初学者只需几步即可搭建开发环境。这种低门槛的特性让初学者可以专注于编程本身,而不必花费过多时间在环境配置上。同时,Go强大的标准库也为初学者提供了丰富的资源,使他们可以在不依赖第三方库的情况下完成许多实际项目,无需与繁芜的第三方依赖“作斗争”。此外,Go程序编译速度极快,可以快速让学员获得反馈。 注:我的极客时间专栏《Go语言第一课》专栏的“03|配好环境:选择一种最适合你的Go安装方法”有对Go环境搭建的系统全面的讲解,欢迎订阅阅读。 4. 面向未来的选择 选择第一门编程语言不仅关乎当下的学习体验,更应该着眼于未来的发展。Go在保持简洁性的同时,涵盖了现代编程的核心概念,从并发编程到网络服务,从系统编程到云原生应用,Go都能胜任。这种全面的能力使得Go成为初学者为未来编程生涯奠定基础的理想选择。 此外,Go在业界的广泛应用也为学习者提供了良好的职业前景。掌握Go的初学者可能会在未来的就业市场中占据优势,特别是在后端开发和云计算等领域。 尽管Go有许多优势,但我们也需要正视其作为第一门编程语言所面临的挑战。接下来,我们就来看看这些挑战! 5. 现实中的挑战 虽然Go语言简单易学,但现实中,无论中外,以Go为第一门编程语言的初学者数量依然不多,这是为什么呢?笔者认为主要有如下几点原因: 首先,Go虽然简单,简化了许多编程概念,但与Python、Scratch等传统的编程入门语言相比,学习曲线依旧“陡峭”,对于完全没有编程经验的初学者而言,理解指针、并发等特性仍然需要一定的努力。此外,Go主要面向后端开发,在前端开发和图形界面支持方面较为有限,对于一些喜欢更直观地通过图形化的方式看到反馈的初学者来说,Go的满足度有欠缺,这可能会影响一些初学者的学习兴趣。 其次,与Python等语言相比,Go主要面对后端开发,在数据科学和机器学习等热门领域的应用相对有限(虽然目前已经在向AI应用开发领域大踏步前进),这可能会影响一些对这些领域感兴趣的初学者的选择。对于许多初学者来说,这些看似更“酷”的应用领域可能比Go所擅长的系统编程和网络服务更具吸引力。 再次,Go在编程教育中的应用仍然相对有限。传统的计算机科学课程多年来已经确立并一直依赖于Java、Python或C++等成熟的编程语言。更新课程设置、编写新的教材、培训教师都需要时间和资源,这种惯性使得Go难以迅速进入教育体系。 最后,相比其他语言(如Java、C++等),Go团队在教育领域的推广较少,缺乏针对教育机构的专门资源和支持(这让我想起了当年Sun在校园推广Java,微软在校园推广C#等,没有对比,就没有伤害),同时由于Go语言的设计更倾向于“实战派”,并不受“学院派”青睐,因此学术界对Go语言研究也相对较少,导致在高等教育机构的推广受限。 6. 小结:平衡与选择 尽管面临这些挑战,Go语言作为第一门编程语言的潜力仍不容忽视。Go语言以其简洁性、并发特性和面向工程的实用型设计,无疑是一个极具吸引力的选择。虽然它可能不是最容易上手的语言,但它提供了一个平衡的学习体验,既不会掩盖重要的编程概念,也不会像Rust那样陡峭得令人望而却步。 同时,我们也需要认识到,没有一种编程语言能够完美满足所有学习者的需求。Go的优势在某些领域可能是无可替代的,但在其他方面可能需要补充。因此,一个更平衡的方法可能是将Go作为编程教育的重要组成部分,而不是唯一选择。比如,对于今天的初学者来说,理想的方案可能是将Go作为主要学习对象,同时辅以其他语言(如Python)来弥补在特定领域的不足。无论选择哪种语言,保持好奇心和学习的热情才是成为优秀程序员的关键。 最后,Go要实现在编程教育中扮演更重要的角色,还需要多方面的努力。Go团队和Go社区还需加强在教育领域的推广,开发更多面向初学者的资源和工具,以激励教育机构将Go纳入课程体系,特别是在教授并发编程等概念时。 如果你对Go语言感兴趣,并且希望系统地学习如何从零开始编写Go代码,我在两年多之前在极客时间开设了“Go语言第一课”的专栏。 这个专栏专为Go语言新手设计,从基础概念到实战案例,逐步带你掌握Go语言的核心知识点。无论你是编程初学者,还是希望掌握一门新语言的开发者,这个专栏都能为你提供有价值的学习资源和实践指导。 Gopher部落知识星球在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时,我们也会加强代码质量和最佳实践的分享,包括如何编写简洁、可读、可测试的Go代码。此外,我们还会加强星友之间的交流和互动。欢迎大家踊跃提问,分享心得,讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落,享受coding的快乐! 欢迎大家踊跃加入! Gopher Daily(Gopher每日新闻) – https://gopherdaily.tonybai.com 我的联系方式: 微博(暂不可用):https://weibo.com/bigwhite20xx 微博2:https://weibo.com/u/6484441286 博客:https://tonybai.com Gopher Daily归档 – https://github.com/bigwhite/gopherdaily Gopher Daily Feed订阅 – [...]

Go 1.23中值得关注的几个变化

2024-08-19 07:18:34

本文永久链接 – https://tonybai.com/2024/08/19/some-changes-in-go-1-23 距离上一次Go 1.22版本发布又过去六个月了,我们如期迎来了Go 1.23版本的发布。 对于Go项目乃至整个Go社区而言,这个版本还有一点额外的意义,那就是这是Russ Cox作为Tech lead,领导Go团队发布的最后一个Go版本了。 8月2日,Russ Cox在golang-dev google group上发文,在领导了Go项目12年后,决定辞去Tech Lead,并将这一角色“传位”给Austin Clements,后者是现任Go core领域(围绕编译器工具链、运行时和发布)的Leader。Cherry Mui将递补,成为Go core领域的新Leader。 注:除了Go core外,Go项目下面还有两个领域的子团队,分别是由Roland Shoemaker领导的Go安全团队(Go Security)和由Rob Findley、Hana Kim共同领导的Go工具链和IDE支持团队。 注:Austin曾在Google担任实习生,在攻读博士学位期间参与了Go项目的早期工作。后来(2014年),他加入了Go 团队,与Rick Hudson合作完成了Go的并发垃圾回收。他还曾参与了当前的抢占式调度器和链接器的开发工作。现在,他领导着Go的编译器/运行时团队。– 来自golang.design 长相有些神似“马特达蒙”的Russ Cox经常活动于GopherCon之类的技术大会上,照片和视频比较多,但Austin和Cherry似乎都很神秘,很少出镜。Cherry Mui居然还是一个巾帼女汉子。如果你和我一样,不是很了解Austin,可以看看这个Austin在GopherCon 2020上的这个视频。 在Russ Cox的领导下,Go如今已经成为云原生领域的基石语言,在我的《都2024年了,当初那个“Go,互联网时代的C语言”的预言成真了吗?》那篇文章中,我谈到Go建立了云原生时代的整体技术栈,地位媲美单机时代的C语言。Go在各大编程语言排行榜的位次也一直在提升,今年Go在TIOBE上最高已经冲到了第七名。在语法特性和工具链方面,Russ Cox带领Go团队先后实现了Go module、Go泛型等重要变化的落地。Go已经证明了自己的成功。 但俗话说:“船大难掉头”!随着Go语言的成熟,用户的不断增多,生态的不断扩大,如何把控好Go这艘大船,持续在正确的方向上航行,便逐渐成为了摆在Go团队面前的一个极具挑战性的问题。另外,在Go演进的过程中,质疑声也从来就没有中断过,尤其是在Go module、Go泛型等提案落地的过程中。Go 1.23引入的自定义函数iterator也曾一度将Go抛上风口浪尖,一些人批评Go忘记了简单的原则,正在走向错误的演进方向上。甚至还出现了Go已经过了流行的顶峰的观点: 这些也同样是Russ Cox留给Austin Clements等新一代决策层的“课题”。 言归正传!让我们来看看Go 1.23版本都有哪些重要的变化吧! 注:在两个多月,我曾写了一篇《Go 1.23新特性前瞻》,如果当时的新变化的实现与如今Go 1.23正式版是一致的,在本文中我就不会再详细说明了,大家可以移步那篇文章了解。 1. 语言变化 Go 1.23中最大的语言变化就是将Go 1.22中引入的试验特性:range-over-func变为了正式特性。我么就先从这个变化说起。 1.1 自定义函数迭代器 一旦你接受了泛型,迭代器就会不可避免地出现 [...]

都2024年了,当初那个“Go,互联网时代的C语言”的预言成真了吗?

2024-08-17 06:17:02

本文永久链接 – https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true 本文最初发表于我个人的微信公众号(iamtonybai),但鉴于图片消息的篇幅受限(<=1000字),一些内容没能如愿展开,这里在博客上重新发布一下,也顺道丰富一下文章的内容。 2012年,七牛云创始人、goplus语言之父许式伟在一次演讲中给出一个大胆的预言:“Go,互联网时代的C语言”。 十余年过去了,我们不禁要问:当初的那个预言是否已经成真? 在讨论这个预言之前,我们先来看在同一份演讲稿中,老许给出的另外三个预判: 它们是: Java语言份额继续下滑,最终被C和Go语言超越; C语言将长居编程榜第二的位置,有望在Go取代Java前重获第一的宝座; Go语言最终会取代Java位居编程榜榜首。 编程语言排行榜有很多,我们就以名气最大的TIOBE刚刚发布的2024年8月排行榜为例,看看这些预判是否成真。 很遗憾,一个也没命中。 在这份最新榜单中,C位列第三、Java位列第四,Go位列第九,相对于前两个月的第七还下降了两位。不过不得不说,老许对C语言的预判还是相对准确的。 那这是否意味着老许最初的那个预言也Miss了呢?个人觉得:并没有。因为这要看从哪个角度来审视。 传统观点认为,C语言被视为系统编程语言的杰出代表,因其卓越的底层操作能力和极致性能而广受推崇。它允许开发者直接与硬件交互,提供了高效的资源管理和快速的执行速度。如果从这样的视角去看待那则预言,那显然Go与“互联网时代C语言”这个评价和地位是不相称的。虽然Go最初的定位也是一门系统编程语言。 但如果我们跳出以“低级操作和性能”为中心的比较框架,而是从不同时代软件技术栈的层次与构建来看,Go与C语言的地位又极其的相似。 在互联网时代到来之前,C语言已经是整个软件技术栈的基石:从操作系统内核、设备驱动程序、中间件到应用程序,C语言凭借卓越的性能、无以伦比的生态,在技术栈的各个层次都有着广泛且核心的应用。 当时针指向云原生时代时,Go语言在云原生技术栈的构建中,发挥了与C语言相似的作用: 云原生“操作系统”:Kubernetes; 云原生“驱动程序”:容器运行时(docker、containerd、podman)、网络插件(Calico、cilium、CoreDNS等)、存储插件(Rook、longhorn等); 云原生“中间件”:数据库(CockroachDB、Vitess、InfluxDB(2.x)、VictoriaMetrics、Dgraph、milvus等)、消息队列(NATS、nsq等)、服务网格(Istio、linkerd2)、API网关/代理(Traefik、emissary等)、镜像仓库/加速器(harbor、Dragonfly)、key-value存储(Etcd、consul、junodb)、安全相关(falco、OPA、vault)、可观测组件(OpenTelemetry、Prometheus、Thanos、Cortex等)、基础设施管理(terraform、dagger)、分布式存储(minio、SeaweedFS、juicefs)、AI大模型运维(ollama)。 应用层:Caddy、gohugo、mattermost等。 我们用一张示意图来横向对比一下: 听我讲到这里,你是不是觉得老许的那个预言好像命中了呢! 当然,从狭义的角度来看,Go与C还有一些地方是很像的,比如:语法简单、跨平台可移植性好等。并且两者还“沾亲带故”:Unix之父Ken Thompson当年和Dennis Ritchie一起发明了C语言,又和Rob Pike等一起设计了Go语言! 最后,回顾许式伟2012年的预言,我们不得不惊叹于其洞察力。Go语言确实在很大程度上成为了”互联网时代的C语言”,但不是通过传统的性能优势,而是通过重新构建了云原生技术栈,从这个角度看,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 博客:tonybai.com github: https://github.com/bigwhite Gopher Daily归档 – https://github.com/bigwhite/gopherdaily Gopher Daily Feed订阅 [...]

通过Go示例理解函数式编程思维

2024-08-11 21:46:57

本文永久链接 – https://tonybai.com/2024/08/11/understand-functional-programming-in-go 一个孩子要尝试10次、20次才肯接受一种新的食物,我们接受一种新的范式,大概不会比这个简单。– 郭晓刚 《函数式编程思维》译者 函数式编程(Functional Programming, 简称fp)是一种编程范式,与命令式编程(Imperative Programming)、面向对象编程(OOP)、泛型编程(Generics Programming)、逻辑编程(logic Programming)等是一类的概念。 注:尽管面向对象范式引入了新的编程思想和技术,但它本质上与命令式编程一样,都关注程序的状态和如何通过改变状态来控制程序的执行流程,因此,OOP仍然属于命令式编程的一个分支。OOP可以看作是命令式编程的一种扩展和补充,它增强了代码的模块化、复用性和可维护性。在接下来,我会统一使用命令式编程范式来指代它们。 但几十年的编程语言的演进和实践已经证明:函数式编程并非银弹,它有优势,更有不足。从编程社区的实际反映来看,纯函数式编程语言(比如:CLisp、Haskell、Scala、Clojure、Erlang等)始终处于小众地位。此外,即便很多主流命令式编程语言在近些年融入了一些函数式编程的语法特性,采用函数式风格的代码依旧比例极低,且不易被广泛接受。许多程序员在面对复杂的状态管理和副作用时,依然倾向于使用传统的命令式编程风格(包括OOP)。。 注:Go就原生提供了一些支持函数式范式编程的语法特性,比如:函数是一等公民(first-class)、高阶函数、闭包、函数迭代器以及泛型等。 造成这种局面的原因众说纷纭,但我认为有如下几个: 首先从人类这个物种的大脑的认知和思维方式来看,命令式编程更接近于人类的自然思维方式,其逻辑与人类解决问题时的逻辑思维相似,即都是以步骤的形式理解问题,且有明确的控制流:命令式语言的控制结构(如条件语句、选择语句和循环)使得程序的执行路径清晰可见,符合人类的直觉理解,这也使得命令式语言更容易被人类大脑所掌握。 其次,命令式编程强调状态的变化,程序员可以直接看到和控制变量的变化,这与人类处理现实世界事物的方式相似。 在上面原因的驱使下,久而久之,程序员便形成习惯与传统,有了积淀,便可以促进命令式编程语言在教育和产业中的广泛应用,使得大多数程序员习惯于这种编程方式(间接挤压了函数式编程的使用空间)。进而使得命令式语言有更丰富的学习资源和社区支持,程序员也更容易找到帮助和示例。 也就是说,命令式编程范式占据主流的根本原因是人类的大脑本身就是命令式的,而不是函数式的。不过也有极少数大脑是函数式思维的,比如发明了TLA+这门形式化建模和验证语言的Leslie Lamport老先生。 那么问题来了!既然学习函数式编程思维是违反人类大脑直觉的,且较为困难,那为什么还是有很多人学习函数式编程思维,并在实际开发中应用函数式编程范式呢?关于这个问题,我们可以从两方面来看。 从主观上说,程序员经常有探索新技术和新范式的内在动力,这种好奇心驱使他们尝试函数式编程,也就是我们俗称的“玩腻了,尝尝鲜儿”。并且,许多程序员视学习函数式编程为一种智力挑战,一种来自舒适区之外的挑战,这种挑战能带来成就感和个人成长。此外,在竞争激烈的IT行业,掌握多种编程范式可以使得个人技能多样化,增加个人的职业竞争力。 从客观上看,函数式编程也确实能帮助程序员提高抽象思维和系统设计能力,这种能力的提升不仅限于函数式编程,还能应用到其他编程范式中。并且,函数式编程为程序员提供了一个新的解决问题的视角和方法,特别是在处理并发和并行计算、复杂数据转换和流处理方面。 学习函数式编程范式,并不是说抛弃命令式范式(或其他范式),而是融合,从主流编程语言对函数式编程的语法特性的支持也可窥见这般。 那么,到底什么是函数式编程范式?它与命令式范式对比又有怎么样的差异与优劣呢?在这篇文章中,我就来说说我的体会,并辅以Go示例来帮助大家理解。 1. 思维差异:命令式编程 vs. 函数式编程 在看过很多函数式编程的资料后(见文后的参考资料一节),我问了自己一个问题:面对同一个实际的问题,用命令式编程范式和用函数式编程范式的核心思维差异在哪里?为此,我基于现实世界的一个典型问题模型(数据输入 -> 数据处理 -> 处理结果输出),并根据自己的理解画了下面两幅图: 命令式编程范式的思维 函数式编程范式的思维 我们先来描述一下上面两幅图中的数据处理流程: 命令式编程:通过I/O操作获取数据,然后解码为自定义类型进行处理,再编码为自定义类型以便I/O操作输出。处理过程中使用函数、带方法的类型和控制流结构(如for、if、switch等)。 函数式编程:通过带有副作用的操作(如I/O操作)获取数据,然后解码数据放入通用数据结构(如列表、元组、映射)进行处理,再放入通用数据结构以便通过副作用操作输出。处理过程中会使用纯函数、高阶函数以及它们的函数组合。 基于上述流程的说明,我们可以看出两种范式核心关注点的差异: 命令式编程范式:更关注类型的封装、类型间的耦合关系、行为集合的抽象(接口)以及对数据在类型实例间的传递的显式控制(if/for/switch)。 函数式编程范式:弱化类型的概念,使用通用数据结构,专注于通过纯函数/高阶函数、不可变数据和函数组合来实现对数据的处理逻辑。“控制流”更加隐含,比如会通过递归、模式匹配和惰性求值等方式实现。建立专门的抽象来应对与真实世界交互时的带有副作用(side effect)的操作。 下面我们通过一个具体的问题来大致体会一下不同编程泛型在解决问题的实现上的思维差异。这个问题很简单:编写一个程序从input.txt文件中读取数字(每行一个数字),将每个数字乘以2,然后将结果写入output.txt文件中。 我们先来用命令式编程范式实现: // fp-in-go/double/go/main.go // NumberData represents the input data type [...]

使用TLA+形式化验证Go并发程序

2024-08-05 07:12:19

本文永久链接 – https://tonybai.com/2024/08/05/formally-verify-concurrent-go-programs-using-tla-plus Writing is nature’s way of letting you know how sloppy your thinking is – Guindon 在2024年6月份举办的GopherCon Europe Berlin 2024上,一个叫Raghav Roy的印度程序员(听口音判断的)分享了Using Formal Reasoning to Build Concurrent Go Systems,介绍了如何使用形式化验证工具TLA+来验证Go并发程序的设计正确性。 TLA+是2013年图灵奖获得者、美国计算机科学家和数学家、分布式系统奠基性大神、Paxos算法和Latex的缔造者Leslie B. Lamport设计的一种针对数字系统(Digital Systems)的高级(high-level)建模语言,TLA+诞生于1999年,一直低调演进至今。 TLA+不仅可以对系统建模,还可以与模型验证工具,比如:TLC model checker,结合使用,对被建模系统的行为进行全面的验证。我们可以将TLA+看成一种专门用于数字系统建模和验证的DSL语言。 注:TLA是Temporal Logic of Actions的首字母缩写,Temporal Logic,即时序逻辑,是一种用于描述和推理系统行为随时间变化的逻辑框架,由Arthur Prior在1950年代后期引入逻辑学。在后面对TLA+的进一步介绍中,大家可能就会逐渐理解为什么Lamport给这门语言命名为TLA+了。 这不是我第一次接触TLA+,去年就花过一些时间了解过TLA+的资料,可能是因为姿势不够正确,没有在本博客留下只言片语,而这次我打算写点有关TLA+的东西。 1. 为什么需要TLA+ 从1999年Lamport发表的论文“Specifying Concurrent Systems with TLA+”以及他2014年在微软的演讲“Thinking Above the Code”中 ,我们大致可以得到Lamport在20多年前设计TLA+的朴素的动机:期望程序员能像科学家一样思考,在编码之前用一种精确的形式化的语言写出目标系统的spec,这个过程类似于建筑架构师在建筑施工之前编制建筑的蓝图(blueprint)。 [...]