从Golang中open的实现方式看Golang的语言设计

Golang的设计目标

$ Golang有很多优点:

  • 开发高效;(C语言写一个hash查找很麻烦,但是go很简单)
  • 运行高效;(Python的hash查找好写,但比Python高效很多)
  • 很少的系统库依赖;(环境依赖少,一般不依赖各种LibPath等)
  • 简单可依赖;(静态类型,不怕Python的动态类型防不胜防的坑;unused import会报错,减少不必要的import;)
  • 可以直接嵌C,也可以编译成so供C/C++调用;(搞不定的坑都可以让C来填;高效的部分golang刷刷刷)

$ 设计Golang的人是怎么想的呢?
参考go/doc/go_faq.html

What is the purpose of the project?
No major systems language has emerged in over a decade, but over that time the computing landscape has changed tremendously. There are several trends:

1. Computers are enormously quicker but software development is not faster.
    计算机运行速度极大提升了,但是软件开发速度没有跟上
2. Dependency management is a big part of software development today but the “header files” of languages in the C tradition are antithetical to clean dependency analysis—and fast compilation.
    依赖管理是软件开发的一大问题,C语言的头文件式管理方式做不到清晰的依赖和快速的编译。
3. There is a growing rebellion against cumbersome type systems like those of Java and C++, pushing people towards dynamically typed languages such as Python and JavaScript.
    现在对Java和C++这种繁重的语言抵制越来越多,推动人们更多的用如Python、JavaScript等动态语言。
4. Some fundamental concepts such as garbage collection and parallel computation are not well supported by popular systems languages.
    一些根本概念如垃圾回收、并行计算在常见的语言中支持的并不好
5. The emergence of multicore computers has generated worry and confusion.
    多核计算机的普及增加了程序员的迷惑和担忧。
We believe it's worth trying again with a new language, a concurrent, garbage-collected language with fast compilation. Regarding the points above:
希望可以做一个新语言,包括并行、垃圾回收、快速编译。
It is possible to compile a large Go program in a few seconds on a single computer.
1. Go provides a model for software construction that makes dependency analysis easy and avoids much of the overhead of C-style include files and libraries.
    Go语言提供了一种软件构建模型,使得依赖分析简单,避免了大量类似C的头文件和二进制分析。
2. Go's type system has no hierarchy, so no time is spent defining the relationships between types. Also, although Go has static types the language attempts to make types feel lighter weight than in typical OO languages.
    Go语言的类型系统没有等级区别,所以不需要花时间去构建类型关系。同时,Go是静态语言类型,使得类型系统相比面向对象语言要轻量很多。
3. Go is fully garbage-collected and provides fundamental support for concurrent execution and communication.
    Go语言支持垃圾回收,提供了重要的并行计算、通信的支持。
4. By its design, Go proposes an approach for the construction of system software on multicore machines.
    通过Go语言的设计,Go语言致力于多核机器上的软件构建更加简单

开发高效 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)。

  1. 在src/pkg/os/file.go:229中找到Open方法的具体实现,调用了OpenFile;
  2. OpenFile涉及到不同的架构不同实现,unix的实现在src/pkg/os/file_unix.go:65,实际调用了syscall.Open();
  3. 在src/pkg/syscall/syscall_linux.go:21,其实现为sys的open;
  4. sys的实现,实际在src/pkg/runtime/sys_linux_amd64.s:23,汇编语言编写通过真正操作系统层面的syscall实现文件操作;

从以上追溯可以看出:

  1. 核心方法指令,直接调用操作系统层面的syscall,所以规避了很多依赖库;
  2. 核心方法指令,直接调用操作系统层面的syscall,避免了中间商赚差价和冗余实现,编译运行直接高效,可靠性直接挂钩操作系统;
  3. 从src/pkg/runtime的其他文件略读,不少为C的实现,相当于在C的基础上封装,减少了灵活性,提高了效率;

总体而言,Golang是没有C灵活,没有Java丰富,做了一个比较讨喜,适合这个时代的折中。

相关推荐