查看原文
其他

“Go 2” 正式落地,中国 Gopher 踏上新征程!

柴树杉 CSDN 2023-01-10

本文来自  CSDN 重磅策划的《2022 年技术年度盘点》栏目。2022 年,智能技术变革留下了深刻的脚印,各行各业数字化升级催生了更多新需求。过去一年,亦是机遇与挑战并存的一年。《2022 年技术年度盘点》将围绕编程语言、开源、云计算、人工智能、架构服务、数据库、芯片、开发工具等核心技术领域,特邀一线技术专家亲临分享自身的技术实践,借此希望能够为更多的行业从业者带来一些借鉴与思考,更好地把握技术的未来发展趋势。

在本篇文章中,来自 Go 开发社区的资深专家柴树杉老师将围绕 Go 语言的技术演进历程,分享对「Go 2」的最新见解,深度剖析 Go 语言在中国的生态发展与企业应用现状。

最后,如果您有对技术趋势的真知灼见,或是深度的应用实践的新见解,欢迎联系 CSDN 投稿,联系方式:微信(hanbb120,请备注投稿+姓名+公司职位)、邮箱(tumin@csdn.net)。


作者 | 柴树杉       责编 | 屠敏
出品 | CSDN(ID:CSDNnews)

回忆 2019 年,正值 CSDN 二十周年时,我曾写过一篇关于 Go 语言的总结文章——《Go语言十年而立、Go2蓄势待发》。彼时年底在 Go 2.0 刚启动时,一场“黑天鹅事件”的突然到来,引发了全民抗疫。

如今时隔三年之后的 2022 年 12 月,疫情全面放开的同时 Go 2.0 也正式落地了。在 2019 年写前一篇文章的时候,作者尚在武汉,在 2021 年因疫情影响全家搬迁到了杭州,工作环境和工作的方向内容也都发生了巨大变化。因此希望通过这篇文章回顾下这 3 年来在周边和 Gopher 社区发生的巨大变化。


当我们在谈 Go 2 时,究竟指的是什么?


2012——初见 Go 1.0

Go 2 是相对于 2012 年 Google 发布的 Go 1.0 的叫法,是代表包含泛型特性的 Go 2.x。在 Go 1.0 发布时,官方团队承诺 Go 1.x 将保持源代码级别兼容,就是所谓的 Go 1.x 代码在后续的 Go 1.x 环境均可以编译(但是因为各种外部的因素,编译可能会遇到很多问题,特别是和平台有关的代码)。

2020——期待 Go 2

因为泛型对于任何一个编程语言中都比较大的特性,当时整个社区都预计包含泛型特性的 Go 将会打破 Go 1.x 不兼容的承诺,因此预期大版本号会同时升级。不过后来官方采取了更为稳妥的渐进开发模式,在 Go 1.18 不破坏 Go 1 兼容性的前提下实现了泛型(当然更激进的标准库革新也没有发生)。因此大家期待的 Go 2.x 并未出现。

标题中所谓的 Go 2 目前在现实中并不存在!

Go 2 vs Go 1.20

作为 Gopher,作者依然自行将 Go 1.18+的 Go 语言作为 Go 2 称呼。这无关于 Go 1 的兼容性承诺——而是包含泛型特性的 Go 语言已经不再是 Go 1 所坚持的“Less is More”的 Go 语言、也不再是 Robert Griesemer、Ken Thompson 和 Rob Pike 三位 Go 发明者设计的 Go 语言(泛型主要由 Ian 操刀)!

正如 C++ 虽然几乎完全兼容 C 语言、但是 C++ 依然是一个新的编程语言,因为 C++  和 C 语言有着完全不同的编程哲学。同样,Go 1.18 的泛型带来的编程哲学的巨大变化,我希望通过某些形式区分它。


Go 网站变更历史


Go 网站风格是 Go 语言变更的风向标,每逢重要的时间节点网站必然会同步跟进。到了 2022 年,Go 语言官网从开源以来走过了 13 年,官网也经历了 4 次大的变化。

2009 年——青涩年华

2009 年,Go 语言刚刚开源时的官网和 Chrome 浏览器一样青涩(首页的 rsc 还是一个帅小伙):

2012 年——迎接第一个重大版本

2012 年,Go 1 刚刚发布是官网首次改版(每次改版表示有重大事件要发生):

2019 年——革新前夕

到了 2019 年重启 Go 2 开发前夕网站再次改版,重新发布了 Logo:

2021 年——迎接“Go2”时代

到了 2021 年 8 月,重启 Go 1.18 前夕,官网再次迎来彻底翻新,这次网站地址也变了:

Go 1.18 最终带来了大家期待已久的泛型特性,网站也增加了更多营销的内容!作者估计以后的 Go 语言将逐步进入运营时代(围观 Go 主仓库变化的同学们其实可以慢慢散了)。


Go 2 泛型终落地


Go 2 的变化当然不仅仅包含泛型这一个特性,其他诸如模糊测试、结构化的文档、工作区、Arena 提案等都是比较大的特性,但是这里就不详细展开了。

认识 Go 泛型

其实 Go 2 的开发从 Go 1.10 逐步启动,到 Go 1.18 泛型落地(具体参考2019 年的总结文章)。如果将 Go 1.18 作为 Go 2 的启始版本,到目前即将进入开发周期 Go 1.20,语言主要有以下的变化:

  • Go 1.18 带来了最大的泛型特性、Fuzz 模糊测试;

  • Go 1.19 为中国的龙芯 CPU 提供了支持;

  • 还在开发中的 Go 1.20 标准库将引入 arena 包提供内存池特性。

总体来说,Go 2 时代不仅带来了泛型的变化,同时也提供了基于 arena 包的手动内存管理机制(area 是很多语言性能测试的大杀器)。

虽然有点后知后觉(其实我自己还在坚守在Go1时代的Go1.17版本),为了免俗我们也简单看下 Go 泛型的例子:

func main() {s := []int{1, 3, 5, 2, 4}fmt.Println(index(s, 3))fmt.Println(index(s, 6))}
func index[E comparable](s []E, v E) int {for i, vs := range s {if v == vs {return i}}return -1}

其中,index 就是一个泛型函数,可以针对不同类型的 Slice 做 Index 查询操作。[E comparable]是在编译阶段定义一个可以被比较的 comparable 的类型 E,然后再基于 E 定义切片和要查询的元素的类型。

在 main 函数调用 index 函数的时候,Go 的泛型编译器会自动进行类型推导得到泛型函数需要的参数类型信息。如果是 Go 1.17 之前的版本,我们可以通过空接口实现类似的函数:

func indexGo17(list, value interface{}) int {sv := reflect.ValueOf(list)if sv.Kind() != reflect.Slice {panic(fmt.Sprintf("called with non-slice value of type %T", list))}if reflect.ValueOf(value).Kind() != sv.Type().Elem().Kind() {panic("type(value) != type(list[_])")}for i := 0; i < sv.Len(); i++ {if reflect.DeepEqual(sv.Index(i).Interface(), value) {return i}}return -1}

因为是在运行时才能检查切片和对应值的类型,可能会出现运行时 panic 的情况,而泛型则可以在编译阶段给出 panic 对应的错误(运行时同时依赖执行路径,编译时则没有函数执行路径的问题)。

因此可以说泛型是类似静态的接口,可以将某些运行时的类型错误左移到编译阶段(并且不依赖执行路径),而其他性能的差别主要是和实现优化有关。

泛型可以说是接口在编译时的形态,有点类似 Rust 等语言中的 trait。同样 Rust 语言 trait 是编译时特性,又延伸出了运行时的 dyn trait。如果将运行时和编译时接口看作是二维坐标系的 X 和 Y 轴,那么 XY 轴的焦点则是 interface{} 空接口,也就是很多语言的 any 类型。

Go 泛型为何用方括弧?

Go 的泛型除了比较弱外(比如内置运算符无法被重载导致很多自定义类型和内置类型代码风格分裂),Go 泛型采用方括弧也是大家吐槽的点。

官方为此专门提供了回答解释这个选择(https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-contracts.md#why-not-use-the-syntax-like-c_and-java):

简而言之,这是为了方便写编译器的 parser。用过 C++ 的老码农应该知道老版本的编译器不能直接写 std::vector<std::vector<int>> 这种,因为 C++ 编译器比较傻不能识别右边的 >> 符号。当然,这确实是一个冠冕堂皇的理由,也有 C++ 反面案例作证。

不过,我更愿意相信用中括弧作为泛型语法是 Go 语言早就想好的(和 parser 无关,那只是官样的文章)。不相信可以查看 Go 的前身 Limbo 的前任 Aelf 的泛型语法(http://doc.cat-v.org/plan_9/2nd_edition/papers/alef/ref):

其中 adt 关键字用于定义新的抽象类型(和 Go 语言的 type 类似),然后定义一个 T 类型的 Stack,这里就是用方括弧。其实方括弧作为泛型参数正在进入主流,Google 新出的 Carbon 语言就是其中之一。


Go 社区的变化


Go 语言目前已经算做是主流语言,社区的各种消息和资料都非常多。我们无法全部展开,重点讲几个点。

Go 官方的开发者报告

Go 博客发布了 2022 年第二季度 Go 开发者调查报告。据介绍,总共有 5752 名开发者参与了本次调查,分享了他们使用 Go 1.18 中新特性的经验和心得。

主要有以下几个重大结论:

  • 泛型已被迅速采用。大多数受访者都知道 Go 1.18 已正式支持泛型,大约四分之一的受访者表示已经用上了。

  • Fuzzing(模糊测试)对大多数 Go 开发者来说是新事物。模糊测试还是一个新玩意,需要官方继续洗脑。

  • 第三方依赖是最重要的安全问题。官方完善了安全问题管理机制。

  • Error handling(错误处理)仍然是一个痛点。

更完整的报告可以参考官方博客:https://go.dev/blog/survey2022-q2-results

中国贡献者俱乐部

中国作为全球最火热的 Go 语言使用者国家,早就有了很多 Go 用户组织,比如 Go 中国、Go 中文网、GoCN、Go 夜读等组织。并且从一开始就有很多中国同学给 Go 贡献代码。

其中韦京光早在 2010 年就深度参与 Go 语言开发,将 Go 语言移植到 Windows 系统并实现了 CGO 支持。之后来自中国的 Minux 实现了 iOS 等诸多平台的移植,并已经很早就加入 Go 语言开发团队。2019 年前一个文章中提到了来自天津的史斌(benshi001)给 Go 语言编译器和运行时提交了很多优化,到现在国内贡献者更加壮大。

因此在 2019 年,Baokun Lee、Ben Shi 和 Meng Zhuo 几位贡献者决定成立一个贡献者组织,抱团取暖。据 Ben Shi 介绍,目前字节跳动、腾讯内部都有团队在为 Go 编译器和 Runtime 做贡献,组织内的小伙伴还贡献了龙芯到支持代码。其中很多小伙伴拥有 Go 主仓库的评审权限。组织的网站:https://golangcn.org/ 。

这是早期的部分小伙伴列表:

在 2021 年部分小伙伴聚会的照片:

正如组织官网所言:Go 语言中国区贡献者俱乐部希望能在这股中国的 Go 语言浪潮中尽其所能,通过鼓励并帮助更多的中国 Gophers 向上游 Go 社区贡献代码,并在国内的 Go 语言社区中定期分享 Go 工具链的内部实现机制,助力国内社区的繁荣发展以及和国内 Gophers 共同学习成长,共同建设国内的 Go 生态,并愿意尝试作为沟通中国 Go 社区和 Go 语言官方的一道桥梁。

Go 支持国产龙芯架构

龙芯的支持代码在 Go 1.18 时已经开发完成,但是因为泛型带来了巨大代码评审工作被推迟到了 Go 1.19。今年 8 月,Go 1.19 宣布正式加入对 LoongArch(龙架构)的支持,至此,LoongArch 指令系统在 golang 社区成为与 X86、ARM 等指令系统并列支持的指令系统之一。其主要作者 Xiaodong Liu 正是 Go 中国贡献者俱乐部的同学。

此次 LoongArch 架构得到 Golang 开源社区原生支持,意味着 LoongArch64 架构 Go 会随着社区同步发展, 为各种云原生项目、微服务架构、DevOps 平台等迁移到 LoongArch 架构奠定了基础, LoongArch 生态建设再次迈出坚实一步,为国际开源软件发展注入中国创造新动力。

以上是来自龙芯官方的报道:http://www.loongeco.cn/article_822.htm

来自字节的 sort 优化

来自字节的同学使用了 pdqsort 算法 + Go 1.18 泛型,实现了一个比标准库 API 在几乎所有情况下快 2x ~ 60x 的算法库。

pdqsort (pattern-defating quicksort) 是 Rust、C++ Boost 中默认的 unstable 排序算法,其实质为一种混合排序算法,会在不同情况下切换到不同的排序机制,是 C++ 标准库算法 introsort 的一种改进。可以认为是 unstable 混合排序算法的较新成果。

以上是 C++ 的性能对比:其理想情况下的时间复杂度为 O(n),最坏情况下的时间复杂度为 O(n* logn),不需要额外的空间。论文地址:https://arxiv.org/pdf/2106.05123.pdf

Go 语言制霸腾讯

今年上半年,腾讯正式对外发布了《2021 年腾讯研发大数据报告》,披露了 2021 年腾讯在研发投入、研发效能、开源协同和技术公益等方面的重要数据。其中关于 Go 语言的重要信息:随着腾讯云计算和大数据相关业务的迅速发展,Go 语言快速增长,首次超越 C++,成为腾讯 2021 年最热门的编程语言。

 

腾讯作为国内使用 Go 语言的大厂,不仅仅提供了很多 Go 语言项目。在 2021 年腾讯还发布了 Go 语言代码安全指南等基础文档:

具体参考:https://github.com/Tencent/secguide

诞生自 Go 社区的国产编程语言

上次文章写在 2019 年疫情之前,期间国内社区诞生了 Go+ 和凹语言两个新的国产通用编程语言。其中 Go+ 是在 Go 语言之上做加法,而凹语言则是针对 WASM 场景对 Go 做减法。

目前 Go+ 已经举行过几次发布会,多次上过 Hacker News 首页,并且在 GitHub 获得了 8k 多的 Star。而凹语言则开源不到半年只在小范围分享过,不过也登上了 Hacker News 首页,获得了 500 多的 Star。

对于一个新语言来说,几年时间都是比较短的。今年也参与了开源中国关于编程语言领域的点评,我希望这些项目能够持续走下去,同时也希望能吸引更多的同学参与。


阿里/蚂蚁 Go 语言相关的变化


因为作者目前在蚂蚁工作,也近距离接触了一些 Go 语言相关的事情,在此详解蚂蚁集团在 Go 语言相关的变化。这里的列表并不完整,只是个人有接触的几个项目。

蚂蚁发布了 Go 编程规范

除了前端 JavaScript,在蚂蚁后端开发 Go 已经成为仅次于 Java 到第二大语言。为了帮助更多的 Go 开发同学编写更符合公司规范的代码,蚂蚁发布了 Go 语言编程规范 V1.0。

目前还在试用过程,希望可以早日可以公开分享。

Dubbogo 连接更多生态

Dubbo-go 项目由于雨在 2016 年创立;2018 年开始组建开源社区;2019 年项目正式进入 Apache 软件基金会。经历三年多不断地迭代和优化,2021 年底 dubbogo 社区正式推出集成新通信协议、新序列化协议、新应用注册模型、新路由以及新的服务治理能力的 v3.0 版本,该版本在前期研发阶段已经拥有了众多生产用户的关注和使用。

目前 Dubbo-go 生态覆盖多种网络协议:Triple、Dubbo、JSONRPC、gRPC、HTTP、HTTP2 等。构建了 dubbogo proxyless mesh。

在 2022 年,dubbogo 社区实现即基于 RocketMQ 的安全 RPC 调用。并与腾讯北极星团队合作,dubbogo 与 PolarisMesh 全面对接,实现了在  TCP/Triple/gRPC 层面的 TLS 安全通信。

dubbogo 社区于 2020 年创建的 apache/dubbo-go-pixiu 项目,实现了 dubbo 网关与 dubbo mesh 的 sidecar,以 HTTP/gRPC 通信方式解决了 dubbo 生态的多语言问题,已经被阿里集团和蚂蚁集团等用户在生产环境采用。在 2022 年与 dubbo 社区合作,融合 istio v1.14.3 后开始构建 dubbo mesh 的控制面,对接 dubbo proxyless mesh 和 dubbo mesh。

dubbogo 社区是阿里开源项目中最活跃的开源社区之一,多年的发展使社区积累了众多热爱开源的活跃贡献者、 Apache Committer 将近 40 人,其中 PMC 成员 9 人。不仅给 Dubbo 以及其他 Dubbo 生态项目示范了通过社区的组织运营帮助项目发展,而且帮助了提升了整个 Dubbo 大社区的活跃度。

由 dubbogo 社区衍生的 seata-go 社区,于今年 11 月底发布了 seata/seata-go 1.0 版本,实现了 seata 的 TCC/AT 两种模式,预计到 12 月底将完成 XA 模式的对接。

MOSN 改进性能分析功能

MOSN 是蚂蚁主要使用 Go 语言开发的云原生网络代理平台,在蚂蚁集团有着几十万容器的大规模生产应用。在这种大规模的应用中,经常会遇到各种内存问题,通常情况下 pprof heap profile 可以很好帮助分析问题。今年 MOSN 在针对 Go 语言优化方面做了更深入的工作。

比如有时候 pprof 也不够用,其实结合 MOSN 可以得到更多的信息。下面结合 MOSN 产生的火焰图:

具体细节可以参考文章:《Go 内存泄漏,pprof 够用了么?

此外,蚂蚁内部实践的 moe 架构已经提交给 envoy 社区了,融合 C++ 和 Go 生态,预计这个月就可以合入 master 了:https://github.com/envoyproxy/envoy/pull/22573

Layotto 多运行时

Layotto 是构建在 MOSN 之上的项目,是蚂蚁开源的多运行时项目。从 Layer otto 名字看就是第八层的意思,简化后成了 Layotto,同时项目代号 L8(参考 Go 社区一个 otto 的 JavaScript 项目的名字,据说命名的灵感可能是来自 V8)。

Layotto 整体架构如下:

在下层对接了各种基础设施,向上层应用提供了统一的,具有各种各样分布式能力的标准 API。对于接入 Layotto 的应用来说,开发者不再需要关心底层各种组件的实现差异,只需要关注应用需要什么样的能力,然后调用对应能力的 API 即可,这样可以彻底跟底层基础设施解绑。

此外 Layotto 还提供了 Go 跟 Rust 版 WASM 的实现,虽然只支持 Demo 级功能,但已经足够让我们看到这种方案的潜在价值。

KusionStack 云原生方向的探索

Go 语言最早的杀手级应用是 Docker、然后是 Kubernetes,可以说 Go 语言目前已经成为云原生时代编程语言的标准。KusionStack 源于蚂蚁集团内部的规模化工程化运维实践,已广泛应用在蚂蚁多云应用交付运维、计算及数据基础设施交付、建站运维、数据库运维等多个业务领域,助力蚂蚁完成从传统运维管理模式到可编程 DevOps 运维模式的转型。

KusionStack 作为一个可编程、高灵活性的应用交付及运维技术栈(https://github.com/KusionStack/kusion)。灵感源于融合(Fusion)一词,旨在帮助企业构建的应用运维配置管理平面及 DevOps 生态。

主要针对:融合专有云、混合云、多云混合场景;融合以云原生技术为主,同时采用多种平台技术的混合平台技术选型;融合多项目、多团队、多角色、多租户、多环境的企业级诉求。

基于 Platform as Code (平台服务即代码)理念,研发者可以快速收敛围绕应用运维生命周期的全量配置定义,面向混合技术体系及云环境,完成从应用运维研发到上线的端到端工作流程,真正做到一处编写,随处交付。目前,比如有赞等外部用户已经通过 KusionStack 改造了很多中间件,并且在部署到诸多生产集群中。


中国 Gopher 踏上新征程


中国作为世界上最大的 Gopher 地区,也同 Go 语言一样走过了十几个年头。经过这么多年的围观和参与,中国的 Gopher 已经逐渐成熟并有了自己的沉淀和理解。

目前 GitHub 上过万 Star 的中国 Gopher 发起的开源项目就有 10 多个,比如:TiDB 代表的分布式数据库;gogs、gitea 代表的 Git 服务平台;比如 go-zero、beego 为代表的网络框架,excelize 提供的 Excel 处理、goproxy 提供的包代理服务等。也有很多中国 Gopher 给 Go 的 runtime 和编译器后端提供了大量改进,包括对龙芯的支持等。

但是随着参与的深入,融入国际开源项目的阻力也越来愈大:比如 Go2 的泛型设计为何没有中国的声音?Go2 为何还没有解决中文名字不能导出的问题?同一个 Issue 由中国社区提出和 Rob Pike 提出为何是两种截然不同的反响(参考 Issue9097 和 Issue45624)?

因此我们需要开始思考如何拓展自己的生态:来自七牛的 Go+ 是国内第一个公开基于 Go 语言扩展的语言,其中一些创新思路值得借鉴;来自草根的凹语言则通过裁剪 Go 并结合 Wasm 社区发展出了自研的后端实现。我不敢说这些项目就一定能够成功,但是这展现了中国 Gopher 们积极探索的态度。

未来已来,未来希望中国 Gopher 们能走的更稳一些!共勉!

作者介绍:

柴树杉,KusionStack(https://github.com/KusionStack/kusion)项目开源负责人、凹语言作者。同时也是国内最早一批 Go 语言爱好者,创建了国内最早的关于 Go 编程的 QQ 群和 Google 论坛;同时也是 Go 代码贡献者、Go 中国贡献者俱乐部成员;组织翻译了《Go语言圣经》、出版了《Go语言高级编程》《Go语言定制指南》等 Go 畅销图书。

参考链接

  • https://mp.weixin.qq.com/s/wE_z7MxDJjIVDN16578tDw

  • https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-contracts.md#why-not-use-the-syntax-like-c_and-java

  • https://go.dev/blog/survey2022-q2-results

  • https://golangcn.org/ 

  • https://arxiv.org/pdf/2106.05123.pdf

  • https://github.com/KusionStack/kusion

  • https://github.com/golang/go/issues/45624

  • https://github.com/envoyproxy/envoy/pull/22573

  • https://github.com/mosn/mosn

  • https://github.com/mosn/layotto

13 年,MySQL 之父赌赢了:另起炉灶的 MariaDB 成功上市!
关关难过关关过,华为云助力游戏厂商“闯关升级”
蔚来用户数据遭窃取,被勒索225万美元 ;英国银行因IT系统宕机被罚4900万英镑;微信成GitHub秘密扫描合作伙伴|极客头条

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存