首先从工程的视角来说,Python 这方面比较弱。谈 Python 有些人会想到 Go,因为从 Python 转向 Go 的程序员也不少,原因就在于 Go 是设计思想最接近 Python 的工程语言,使用者的心智负担也是非常低的。但是 Go 语言的设计者心中基本只有工程,大家看 Go 的官网就知道,它最关心的一个词是 scale。也就是如何实现一个大型的工程,实现一个代码量非常庞大,但是仍然在工程师掌控之中的工程。所以它没有在意低门槛,它在意的是如何去实现工程上的 scale。
所以从这两方面去看, Go+ 既然是面向全民的编程,那么我们自然会去关注如何把 Go 和 Python 的优势融在一体,把 Go 的工程能力和 Python 的低门槛化结合。
除了这两个很特色的功能外,Go/Go+ 混合编程也将得到增强。目前,Go/Go+ 的混合编程还不支持调用 Go 的泛型。我们知道 Go 的 v1.18 版本,引入了非常重要的特性就是泛型,但现在 Go+ 还不支持 Go 的泛型。那我们在 v1.2 版本也会去支持。我们不是在 Go+ 里去定义泛型,而是调用 Go 的泛型。
基于这样方式,我们是让 Go+ 能够对泛型概念有最小化的能力,因为泛型是一个比较复杂的概念,但我们并不希望 Go+ 变得特别复杂。从长远来看,Go+ 对泛型实际上持非常开放的态度,也许有一天会全面支持泛型,但我们不会把它看成优先级很高的东西。如果真需要用泛型,我们希望是通过和 Go 的混合工程来达到。
我们接下来重点讲讲这两个特色功能,类文件和 c2go。
先聊类文件。类文件最直白的一个解释,就是我们用一个文件去定义一个类。下图右侧就是用 Go 去写类的方法,想必大家非常熟悉。
我们可以看到第一句是 import C,但是它和 Go 的语义是完全不同的,在 Go+ 里它其实是 C/github.com/goplus/libc 的缩写。那我们可以看出,这个例子中我们调用了 2 个 C 函数:printf 和 fprintf,使用了一个 C 变量 stderr。另外还有一个比较有意思的地方,是字符串,我们看到在 Go+ 的标准字符串前面写一个 C 前缀,就代表 Go+ 里传入 C 的字符串常量,这实际上是一个 Go+ 的语法。但是有了这个语法以后,会使得在 Go+ 里调用 C 的代码会非常精简,不至于像 cgo 一样,会有一个从 Go 字符串转化成 C 的字符串,并且最后还要释放它这样一个过程。
这是一个非常小的例子,但是我们可以看到 c2go 在表达上,是能够让大家感觉到好像 C 和 Go 的包是没有区别的。我们引入 C 的包和引入 Go 的包,基本使用上大差不差。而且在所有的细节上,都会让大家感觉 C 的模块好像就是 Go 的模块,当然同时也是 Go+ 的模块,这是我们希望能够达到的最终效果。这也是我们在 Go+ 里无缝兼容 C 的一个逻辑。
当然当前 c2go 还是一个预览版,它连 Beta 版都算不上。c2go 当前已经完成了 C 语法 99% 以上的兼容,它没有完成的部分,主要在于标准 C 库的迁移,它的完成度可能只有 5%,处在非常早期的阶段。对 c2go 来说,它最主要挑战首先在于跨平台。一方面是 C 标准库(libc)的跨平台,另一方面如何让 c2go 对所有的 C 工程都可以轻松实现跨平台能力,同样是非常重要的能力建设工作。
单从 libc 本身来说,其实无论是 syscall、pthread,都有比较大的工作量。syscall 现在我们已经支持了 mac 版本,但 Linux 和 Windows 还没有支持,那 pthread 就更不用说了,这是我们接下来工作量最大的一个板块。所以 c2go 接下来最重要的是整个标准 C 库的迁移,它本身就是比较庞大的工作。
以上就是当前 Go+ v1.2 版本想要解决的事情,当然还有支持 Go 模板调用的小细节,我们就不展开了。基本以上几个点构成了 Go+ 的特色能力,无论是类文件,还是对 C 的兼容,以及 Go 和 Go+ 的混合工程,都使得 Go+ 有了非常好的底子。