每一次 Go 的版本更新,都像是编程语言进化史上的一小步,却往往能在开发体验和生态中带来一场不小的波澜。Go 1.23 的发布便是如此。这一版本在语言特性、工具链和标准库的多方面进行了深度打磨,为开发者提供了更高效、更易用的编程环境。然而,这些更新并非简单的功能叠加,而是一次向语言设计哲学致敬的探索。
从迭代器支持看 Go 的简约哲学
语言特性方面,Go 1.23 对 for-range 循环新增了对迭代器函数的支持。这看似只是一个简单的“语法糖”升级,背后却是 Go 对开发者需求与语言设计哲学的巧妙平衡。
在传统 Go 代码中,开发者常需要自行实现迭代逻辑,而这些逻辑往往因复杂性而显得繁琐。通过支持迭代器函数,Go 提供了一种更加优雅的解决方案,让复杂的迭代逻辑能够以模块化的方式封装,并与语言特性无缝结合。
为什么这项改进重要?
迭代器函数的引入,实际上是对 Go 一贯简洁性的一种强化。它让开发者能够以类似 Python 或 Rust 的方式遍历自定义数据结构,而无需引入额外的语言复杂度。这种设计并不是简单地“迎合”用户,而是精心考虑后实现的一种更贴合开发者直觉的特性。
从更大的视角看,这一改动标志着 Go 语言正逐步从“高效工程语言”向“优雅开发语言”转变。在这一方向上,Go 保留了极简主义,同时也为开发者带来了更多表达复杂逻辑的可能性。
泛型:下一阶段的序幕
泛型的引入被认为是 Go 语言近十年来最重要的变革之一。然而,Go 对泛型的态度始终是“慎重且克制”的。1.23 版本中,泛型类型别名的预览支持是对这一特性的进一步探索。
几个月之前,Slashdot 转载了Robert Harper教授的一篇博客,说卡内基梅隆大学计算机系把”面向对
象编程“从大一新生的必修课中删掉了,其原因是
Object-oriented programming … is both anti-modular and anti-parallel by its very
nature.
这两个原因(anti-modular和anti-parallel)都是很重的指责了;尤其是anti-modular,因为OO的基
本思想通常被理解成“封装”,从而实现模块化。
我是在1995年第一次听说“面向对象”(Object Oriented)这个说法。当时在学习正在成长过程中的
C++,用的是Borland C++ 1.0。从那时开始的很多年里,”类“(class)、“对象”(object)和
“方法”(methods),以及在这些概念之上构建的”继承“(inheritance)和”多态
“(polymorphism)都是我理解中OO最核心的思想。我猜大多数程序员在这方面的认识都和我差不
多。
但是“封装”真的是OO的本质嘛?直到最近为了给iPhone写个玩具程序而学习Objective-C(一种非
常古老和原始的面向对象编程语言)的时候,才注意到早在1998年,OO之父Alan Kay就曾经在一篇
邮件中说,他很后悔发明了“object”这个词,从而误导大家,把注意力都集中到“封装”,而忽视了
OO的本质——messaging(消息传递)。Alan Kay的原话是:
The big idea is “messaging” … . The key in making great and growable systems is
much more to design how its modules communicate rather than what their internal
properties and behaviors should be.
Objective-C的设计是非常强调“消息传递”(messaging)的——对一个object的method的调用,
被称为“给这个object发了一个消息”。为了突出调用method时指定的参数(parameters)实际上
是消息中的一些内容,Objective-C不惜把method的定义方式都做了相对于C的很大的修改,从而把
参数嵌入在method的名字里。比如在一个叫做myWebView对象中搜索一段文字,要求不区分大小写,
从前往后搜索,用Objective-C来描述是:
很明显,c代码要比java简洁得多。本来一个函数可以解决的问题,OO却告诉我们需要一个类,于是就多出了许多代码。我认为编程时一条重要的原则就即:no more, no less. 上述java代码很难使我们认为它是美的。
其次,面向对象方法在一些时候(其实说是很多时候也不为过)并不符合数学的思维方式,而至少当前我们使用的计算机还是基于数学的理论基础创造的。同样还是上述例子,当我们在数学中解决交换数值问题是该是如何思维的?当然是把要交换的内容作为参数传 入函数。正如Joe Armstrong所说,数学的思维方式中数据和函数时分开的。数学家们不会也不许要将这两者粘合在一起构成一个对象或是其他什么东西。当然,按照Martin Vilcans反驳Joe的文章《No, that’s not why oo sucks》中指出Joe并没有提出合理的解释来证明为何数据和函数应当分开。那么请思考以下情况:假设我们现在有两个类: Class A 和 Class B, 我们需要在A的实例中操作B实例中的某个数据,按照面向对象的设计,我们可以有这两种方式: