语言的需求
注意一下仅讨论Java、C++和Go
语言的出现是为了解决什么问题?个人见解,是为了解决程序的问题。
程序的三大功能是通信、存储、计算,而语言亦是如此。
先放开通信不谈,我们只考虑存储与计算
在语言中,我所认为的存储应当是属性, 而计算对应的是函数/方法
而相对应的,产生了两套编程模式,第一套叫做oo,第二套叫做op
在op模式中,承载数据的结构叫做结构体(structure),而处理数据的叫做函数(function) (当然像pascal语言中也有过程一说)
在oo模式中,语言想办法把op中的结构体和函数放到一起处理,定义为一个对象,对象拥有属性(attributes)和方法(methods)
但实际上,不论哪种方法,都是为了解决数据的“存储”与“计算”问题
并发编程(TODO)
想写一写我所理解的并发编程背后的设计哲学
首先C++和Java都是用锁、原子变量和信号量的方式来进行通信的,即使用共享内存来进行通信。而Go是使用通信来共享内存,所以这里分两块来说。
对于Java和C++的并发编程问题,其实就是提供一系列的API以控制好临界区与线程之间的竞争关系
对于临界区是一个变量的情况,可以提供原子变量的设计供开发者使用。
而对于临界区是一个代码片段的情况,则提供互斥锁mutex来避免竞态条件。
实际上有了mutex,单纯的竞态条件就已经不存在了
但是这里还有许多问题
- 对于mutex,可能会出现n个线程阻塞在同一个临界区的情况,因此提供condition条件变量来让开发者可以自行决策当unlock时究竟唤醒哪一个线程
- mutex需要手动lock和unlock,所以提供了lock_gurad来自动lock和unlock。(所以lock_gaurd是不是可以类比为智能锁233)
- condition的notify和wait接口通信,本质上是在传输一个布尔变量。但如果我们想传递一个对象或者一个字符串呢?虽然可以通过开全局变量的方式来解决,但是C++引入了promise和future来更直接的完成这种操作
- 常见的thread.join并不能获取线程的返回结果,因此提供了async API来使得开发者能够获取线程返回结果
OO与OP
OO/OP的实现方式
Java: interface + abstract class + class
Go: interface + struct。Go语言不允许在struct中写方法,强行把属性和方法分开了。但是C++可以在.h文件中定义方法且做一部分实现。我猜Go不允许写方法的原因是,当C++中出现方法的删除时,需要删除.h中的定义以及.cpp中的实现,做了重复的工作。而Java则规定方法的实现不能在class外部。所以Go和Java算是两个极端了吧hh,C++夹在它们中间。
C++: interface(使用纯虚函数实现,纯虚函数不能有实现) + abstract class(使用虚函数,虚函数可以有实现)+ class(可以重写其父类的虚函数和非虚函数)。具体在实现时,一般用.h文件来定义class的声明信息,在.cpp中写具体的实现
我的理解是,不论interface还是abstract class,其本质还是对class进行分类
有的class需要大量的被继承,且每个方法对于不同的类实现都不同,因此可以被抽象为interface
有的class需要被继承,但是含有一些确定的公共方法,因此可以被抽象为abstract class
语法格式
异常的实现方式(TODO)
Java、C++: try...catch
Go: nil
func设计
为什么go的return类型要放在后面?
我猜是因为go可以返回多个变量,如果放在前面且类型为void则不会写任何东西,设计的不够优美
对于class/struct的考量(TODO)
对于基础数据类型的考量(TODO)
命名规范
对于Java语言,基本上遵循着驼峰式命名法(对于类名首字母大写,变量名首字母小写)
对于C++语言,基本上采用下划线分割的方法(当然openGauss里驼峰式和下划线式混用就多少有点奇葩)。像cmu15-445的bustub,对于成员变量都在最后加了下划线,非常友好
而对于Go语言,变量的命名方法与是否是private变量有关,因此一般采用驼峰式命名法,而是否大小写根据成员的具体情况来定.
另外在这里记录一下我所想到的关于变量命名的一些tips
结合上面所说,一个函数中的中间变量本质上还是对那三种数据的Read、Update。
总的来说,都是临时变量,所以在声明时可以全部以tmp开头,同时在结尾加入类型标识符,例如ptr, num来表示其所表达的数据类型
打包方式
- C++提供了CMake来生成MakeFile,并使用make来进行编译生成可执行文件
C++并没有大一统的模块管理工具,习惯使用CMake + GitModules的方式进行管理
例如 https://github.com/ClickHouse/ClickHouse/blob/master/.gitmodules
Java提供了maven package命令来生成jar包,最终将jar包放到不同的平台上,使用java运行jar包即可。(实际上,Java所谓的“一次编译, 到处运行”只是将对操作系统的判断逻辑托管给了不同平台下的JRE而已。)
Go提供了go build命令来进行打包