Golang设计哲学的深度解析

发表时间: 2024-03-12 10:52

golang简介

Google是一家顶尖的创新与大神集结的地方,员工的工作方式也很特别,叫做“20%Time”,即允许工程师拿出20%的时间来研究自己喜欢的项目。比如说语音服务Google Now、谷歌新闻Google News、谷歌地图Google Map上的交通信息等,全都是20%时间的产物,而Go语言也是诞生于此。

2007年9月20日的下午,在谷歌山景城总部的一间办公室里,谷歌的大佬级程序员Rob Pike启动了一个C++工程的编译构建。按照以往的经验判断,这次构建大约需要一个小时。利用这段时间,Rob Pike与谷歌的另两个大佬级程序员Robert Griesemer和Ken Thompson进行了一次有关设计一门新编程语言的讨论,主要围绕以下C++几个痛点:

  1. 计算机硬件技术更新频繁,性能提高很快。目前主流的编程语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能。
  2. 现有编程语言风格不统一、计算能力不够、处理大并发不够好,目前缺乏一个足够简洁高效的编程语言。
  3. 企业运行维护很多C/C++的项目,C/C++程序运行速度虽然很快,但是编译速度确很慢,同时还存在内存泄漏的一系列的困扰需要解决。

接着大佬们决定在C语言的基础上,进行修正一些明显的缺陷,删除一些被诟病较多的特性,增加一些缺失的功能,具体可见于Rob Pike关于go设计思路的那封邮件:

使用import替代include。
去掉宏(macro)。理想情况是用一个源文件替代.h和.c文件,模块的接口应该被自动提取出来(而无须手动在.h文件中声明)。
语句像C语言一样,但需要修正switch语句的缺陷。
表达式像C语言一样,但有一些注意事项(比如是否需要逗号表达式)。
基本上是强类型的,但可能需要支持运行时类型。
数组应该总是有边界检查。
具备垃圾回收的机制。
支持接口(interface)。
支持嵌套和匿名函数/闭包。
一个简单的编译器。
各种语言机制应该能产生可预测的代码。

自此之后 Robert、Rob 和 Ken 三个人开始在 Google 内部进行了Go的研发,一直到了 2009 年,Go 正式开源了,加上Go的三位作者在业界的影响力以及谷歌的加持,开源后的Go语言吸引了全世界开发者的目光,成为当年2019年TIOBE排行榜的年度最佳编程语言。

而如今Go语言几乎是云原生开发的钦定语言,生态十分庞大,且各个都是杀手级别的项目,如Web框架的beego和gin;微服务框架go kit和Istio;容器编排的kubernetes和swarm;服务发现的consul和etcd;中间间的redis集群codis,rpc框架grpc,游戏服务器leaf,区块链公链以太坊(Ethereum)、联盟链超级账本(Hyperledger Fabric)、分布式关系型数据库TiDB和CockroachDB、云原生监控系统Prometheus等等。

golang设计哲学

这里整理出go语言设计者Rob Pike的一些公开演讲,然后提炼出golang设计之初的哲学之道,这些演讲分别是:

  1. Concurrency is not Parallelism. Rob Pike at Waza 2012

2. Less is exponentially more. Go SF meeting in June, Rob Pike 2012

3. Simplicity is Complicated. dotGo , Rob Pike 2015

大道至简

go语言设计最本质的初衷就是简单,希望程序员的工作量最小化,利用Go本身少量的特性,并通过组合的方式去解决实际问题,而不是堆语言本身的特性功能。即一件事情仅有一种方式或数量尽可能少的方式去完成,这大大减少了开发人员在选择路径方式及理解他人所选路径方式上的心智负担。

少量的特性:

  • 简洁、常规的语法(不需要解析符号表),它仅有25个关键字;
  • 内置垃圾收集;
  • 没有头文件;
  • 显式依赖(package);
  • 没有循环依赖(package);
  • 常量只是数字;
  • 首字母大小写决定可见性;
  • 任何类型都可以拥有方法(没有类);
  • 没有子类型继承(没有子类);
  • 没有算术转换;接口是隐式的(无须implements声明);
  • 方法就是函数;接口只是方法集合(没有数据);
  • 方法仅按名称匹配(不是按类型);
  • 没有构造函数或析构函数;n++和n--是语句,而不是表达式;没有++n和--n;
  • 赋值不是表达式;
  • 在赋值和函数调用中定义的求值顺序(无“序列点”概念);
  • 没有指针算术;
  • 内存总是初始化为零值;
  • 没有类型注解语法(如C++中的const、static等);
  • 没有模板/泛型;
  • 没有异常(exception);
  • 内置字符串、切片(slice)、map类型;
  • 内置数组边界检查;
  • 内置并发支持;

正交解耦,组合使用:

  • Go语言无类型体系(type hierarchy),类型之间是独立的,没有子类型的概念;
  • 每个类型都可以有自己的方法集合,类型定义与方法实现是正交独立的;
  • 接口(interface)与其实现之间隐式关联;
  • 包(package)之间是相对独立的,没有子包的概念。

偏好并发

并发是指同时处理很多事情,而并行是指同时能完成很多事情。两者不同,但相关。一个重点是组合,一个重点是执行。并发提供了一种方式让我们能够设计一种方案将问题(非必须的)并行的解决。我们举一个小地鼠运图书的例子,假设我们只有一个地鼠,最开始从书堆里装书到小推车里,然后运送到火堆里烧掉,这么一个任务过程:

并行的思维是这样的,所有东西都增加一倍,让他们能真正的相互独立不干扰,这样吞吐速度会快一倍。

现在我们采用并发组合的思维,将任务拆分,四只地鼠组成了一个优化的工作流程,每只只做自己一种简单的工序如果任务布置的合理,这将会比最初一个地鼠的工作快4倍。

我们还可以继续优化分解力度,增加了“暂存区域”,上半区的地鼠只负责运送到中转站,这样就能增加更多的地鼠,效率也更加提升。

我们通过在现有的工作流程里加入并发过程从而改进了执行效率。地鼠越多能做的越多;工作效率越高。这是一种比仅仅并行更深刻的认识。即:并发程序的结构设计不要局限于在单核情况下处理能力的高低,而要以在多核情况下充分提升多核利用率、获得性能的自然提升为最终目的。

除此之外,并发与组合的哲学是一脉相承的,并发是一个更大的组合的概念,它在程序设计层面对程序进行拆解组合,再映射到程序执行层面:goroutine各自执行特定的工作,通过channel+select将goroutine组合连接起来。并发的存在鼓励程序员在程序设计时进行独立计算的分解,而对并发的原生支持让Go语言更适应现代计算环境。

golang运行环境搭建

[root@localhost ~]# wget https://golang.google.cn/dl/go1.19.linux-amd64.tar.gz[root@localhost ~]# tar -xvf go1.19.linux-amd64.tar.gz -C /usr/local/[root@localhost ~]# cd /usr/local/[root@localhost ~]# cd /home[root@localhost ~]# mkdir go[root@localhost ~]# cd /home/go[root@localhost ~]# mkdir bin[root@localhost ~]# mkdir src[root@localhost ~]# mkdir pkg[root@localhost ~]# sodu vim /etc/profile[root@localhost ~]# export GOROOT="/usr/local/go"[root@localhost ~]# export GOPATH=$HOME/go[root@localhost ~]# export GOBIN=$GOROOT/bin[root@localhost ~]# export PATH=$PATH:$GOBIN[root@localhost ~]# source /etc/profile[root@localhost ~]# go version[root@localhost ~]# go env[root@localhost ~]# go env -w GOPROXY=https://goproxy.cn,direct`

go语言语法不打算详细介绍了,后面将会用敏捷迭代的方式写几个go的小项目,然后将go语法(一些奇特的特性)及敏捷开发的知识运用到其中, 好了,那我们就继续向前,猪突猛进吧~~

Reference

Go语言精进之路 (豆瓣) (douban.com)

Easy 搞定 Golang设计模式 · 语雀 (yuque.com)

Golang修养之路 · 语雀 (yuque.com)

8小时转职Golang工程师 · 语雀 (yuque.com)+

三分钟了解Go语言的前世今生 - 掘金 (juejin.cn)

Golang/Golang基础/1_Go语言发展简史/README.md · 陌溪/LearningNotes - Gitee.com

Why did the big guys at Google develop the new language Go? - SegmentFault 思否

Go coding in go way | Tony Bai

[翻译]大道至简(原标题:少是指数级的多) - Gopher beyond El[i]phants (mikespook.com)

Go 设计哲学:少即是多,哪里来的? - 掘金 (juejin.cn)

Go语言趣味教材:并发不是并行 (aqee.net)