Golang有很多优点:
- 开发高效;(C语言写一个hash查找很麻烦,但是go很简单)
- 运行高效;(Python的hash查找好写,但比Python高效很多)
- 很少的系统库依赖;(环境依赖少,一般不依赖各种LibPath等)
- 简单可依赖;(静态类型,不怕Python的动态类型防不胜防的坑;unused import会报错,减少不必要的import;)
- 可以直接嵌C,也可以编译成so供C/C++调用;(搞不定的坑都可以让C来填;高效的部分golang刷刷刷)
开发高效 VS 运行高效
一般情况下,开发高效需要有丰富的表达、高级的功能、智能的调度;运行高效,需要又简洁的逻辑、明确且直接的指令。
丰富的表达 VS 表达转换和优化,需要冗余的支撑,包含庞杂的兼容,简单的使用背后是复杂和圈圈绕绕的逻辑,成千上万的指令,严重影响效率;
如果我需要达成golang的优点,解决其中的矛盾,该怎么做呢?无非是开源节流,或者找到一种和谐的划分,既丰富包容又简单高效
- 节流
- 减少中间层级;(降低转换次数,减少中间商赚差价)
- 表达路径优化;(降低表达的丰富性、减少冗余实现的可能,比如open只有一种实现方法,所有用刀open的都这么用)
- 严格的语法逻辑,尽量少的语法糖 (减少表达的语法解析,限制横向冗余可能性)
- 更优的调用层次划分,尽量减少同一功能的冗余低效实现 (减少表达的纵向冗余可能性)
- 开源(一定程度降低丰富性,提升效率,把丰富性的空间留给上层)
- goroutine的协程调度,从有限的线程资源和并发间隙中挖掘可能性
- map和channel等一些基础设定,从语言要素角度,找到降低丰富性,但是强大又高效(既开发高效,也运行高效)的点
Golang的语言设计
首先Golang是一种编译型语言,从code编译链接后是机器码。C、C++都是这样的,我们不得不想到GCC。
GCC,GNU Compiler Collection;GUN,GNU's Not Unix。
GNU是*的操作系统,GCC是*操作系统都编译器集合,Golang确实也是GCC中断一个Option。
我们常用的Golang两种编译器:gc(Golang Compiler);gccgo Compiler。
- gccgo是符合GCC标准的compiler,支持GCC的很多Option
- gc并不完全符合GCC标准
Golang的语法和功能都是要通过Compiler编译链接实现的,这些都可以在go main和gccgo的源码中找到答案。
比如os.Open()是我们常用的一个方法,这里我们以go1版本的代码去研究unix上amd64架构的实现:commit 6174b5e21e73714c63061e66efdbe180e1c5491d (HEAD, tag: go1)。
- 在src/pkg/os/file.go:229中找到Open方法的具体实现,调用了OpenFile;
- OpenFile涉及到不同的架构不同实现,unix的实现在src/pkg/os/file_unix.go:65,实际调用了syscall.Open();
- 在src/pkg/syscall/syscall_linux.go:21,其实现为sys的open;
- sys的实现,实际在src/pkg/runtime/sys_linux_amd64.s:23,汇编语言编写通过真正操作系统层面的syscall实现文件操作;
从以上追溯可以看出:
- 核心方法指令,直接调用操作系统层面的syscall,所以规避了很多依赖库;
- 核心方法指令,直接调用操作系统层面的syscall,避免了中间商赚差价和冗余实现,编译运行直接高效,可靠性直接挂钩操作系统;
- 从src/pkg/runtime的其他文件略读,不少为C的实现,相当于在C的基础上封装,减少了灵活性,提高了效率;
总体而言,Golang是没有C灵活,没有Java丰富,做了一个比较讨喜,适合这个时代的折中。