本文部分转自系统编程语言明日之星-GO作者淘宝余锋写于2010年
Go语言由Google提供支持,于2007年 9月开始浮出水面,出自Rob Pike、 Ken Thomason等大师之手,是一种 支持并发和垃圾回收的编译型编程语言。
Go语言是基于BSD许可发行的开源项目, 目前只支持Linux、Mac OS X和Windows平台。 由于团队资源及社区规模的限制,目前Go还无 法支持更多的操作系统,因此需要更多的参与者 来进行移植。
Go语言创建伊始,就目标明确——创建一种高性能、开发迅速、安全且富有趣味的系统编程语言。各种高性能的网络服务器、文件存储系统、数据库等,都非常适合使用Go进行开 发。当然Go也可以运用在其他领域,Go的官 方网站golang.org就是使用gdoc实现的。
Go 已经在Google公司内部尝试使用,但是并没有大规模地部署,因此仍处于试验阶段,需要丰富的测试和考验。
Go已经给了我们一个华丽的亮相,在工程层面,Go语言官方目前还没有自己的编辑器, 但是发布包带了Emacs、VI以及Xcode 的插件,方便用户的编辑。它目前有2个编译 器:源于Plan9的Native 8/6g编译器和以GCC 为后端的Gccgo。 Gccgo能编译出来更高效的 代码,还可以和其他的gcc库相链接。但是遗 憾的是Gccgo尚未实现垃圾收集,Goroutine 通过pthread实现,调度开销大且栈空间占用 多,而且编译时间较长,无法在实际项目中使 用。 排错器和调优器目前还不大可用。
我看好Go的原因是,这个语言不是凭空或者实验室设计的,而是填补过去10年在系统编程软件方面的不足。作为系统软件的编写者,经常会深深地感到目前常见系统语言在面对大 规模网络应用的力不从心,在不断涌现的多核 心硬件前的无奈,在多线程和各种锁中间的痛 苦,在不停地制造各种各样的轮子的困惑,以及在使用很原始的排错器的低效。Go拥有的这些现代特性都是系统用户梦寐以求的,既结合了动态语言的弹性,又有了静态语言的安全性 和高性能。Rob Pike指出Go代码的编译基本 上可以达到C语言的速度,几乎可以在瞬间完 成。而在运行效率上已经和C语言很接近,同 时支持多核心并发运算。来自语言性能比较网 站Computer Language Benchmarks Game 的数据也验证了这一点。目前这个Go社区非常 活跃,新的特性和包在不断地被提出和加入,加上有Google在背后强力支持和推广,个人认 为应用前景非常广阔。
Go能解决什么问题呢?
我们在编写系统程序时总是会面临以下挑战:
- 硬件发展得很快,软件技术总是突 破得很慢;
- 复杂的系统依赖性很强,平 台、库、管理这些依赖相当麻烦;
- 目前 可用的系统语言如C++、Java太笨拙,也太复 杂,在处理复杂情况时感觉力不从心;
- 复杂的内存管理和资源管理;
- 多核心机器的涌现,
在未来几年里面128核心的机器应 该会很常见,我们难道还是用最原始的线程机制和同步原语来面对?大部分系统语言并不是设计来解决这些问 题的,而且新涌现的大多数程序库也并没有 改善这些问题,相反加剧了复杂度。正如Rob Pike说:“我们开发Go,是因为近10年来开发系统程序之难让我们有点沮丧。 这时候Go 来拯救我们啦!”
设计目标
- 系统编程语言
- 快速编译和执行
- 类型安全性和内存使用安全
- 很好的支持并发计算
- 高效低延迟的垃圾回收算法
设计原则
- 更少的关键词,减少无谓的输入
- 保持概念正交
- 保持简单 减少类型,无类型层次,避免罗嗦
语言特性
Go语言脱胎于C语言,同时还从社区的其他语言如 Pascal、 CSP、Occam借鉴了很多特性,添加了如包管 理、反射、 垃圾回收器、动态类型、并发以及并行机制等。
它有一些有趣的特性:
- 融合多种语言的特性,各个社区的人都感觉会很熟悉,特别是C、Lua、Python社区的用户非常容易上手。
- 支持面向对象编程,但是不支持层次继承。
- 清晰、精确的语法。
- 大写符号导出公共符号,小写是私有的。
- 函数或者块开始注释是文档,方便gdoc生成文档。
- 改进的If、Case复合语句,允许在条件判定前,执 行初始语句。Case不支持自动fall through,支持多个判 断条件和表达式。
- 轻量的类型系统,强类型,没有隐式的转换,显式 类型转化。
- 指针运算由slice代替,提高安全性的同时也有很高 的效率。
- 内置基本数据类型数组和字典。
- type:相当灵活的struct,支持匿名字段,复用看起 来很优雅。
- 灵活但独特的interface: 接口类型, 接口实现分 离。若一个struct实现了interface声明的方法则视为实现 此interface。通用类型interface{}用来表示同样类型,用 于实现包容器和用于参数省略的场合。
- range:for语句支持通用的迭代,支持数组、字 典、通讯管道。 特别是通讯管道结合Goroutine,由生产 者负责在一端输入数据,range充当消费者,从另外一端 消费数据。
- reflection:用于实现多参数机制和实现比如XML、 JSON库,很直观地把结构的字段名和值映射起来,但是 执行效率不高。
- defer负责资源的自动释放,有效地避免资源泄漏。
语言亮点
- 闭包:函数是第一类对象。有了闭包,我们很容易把 数据和函数结合在一起,形成一个独立的执行体,无需关 心数据的泄漏,是并发编程的基础。
Channel:CSP的核心思想是通过消息共享,而不 是内存共享。而消息共享机制就是通过Channel来传递消息,有同步和异步之分。Channel在生产者和消费者之间 架设起沟通的桥梁,承担起传统语言消息队列的作用。 - Goroutine:Goroutine是使并发编程变得容易的核 心。实现上是通过系统的线程来多路派遣协程,使得函数 的执行看起来独立。当一个协程阻塞的时候,比如说费时 的系统调用,调度器就会自动把其他协程安排到另外的线 程去执行,从而保证了系统的不间断运行。这个调度对于 程序员是透明的,从用户的角度来看,协程在一直运行。 而且这个调度的开销非常小,典型的CPU每秒钟可以调度 百万次,协程还支持堆栈的自增。这两个设计使得我们可 以创建大量的goroutine,模拟现实世界对象的行为,大 大简化了程序的设计和实现。
- Network支持:目前支持Tcp/Udp协议,有统一的编 程接口,方便未来支持更多的协议,通过内核POLL支持 成千上万的并发连接。在网络读写暂时无效的时候,网络 模块会自动把该句柄注册到系统的poll set,并且让出执行 权,等待读写事件的发生。一旦读写事件得到通知,网络 模块内部通过Channel通知刚才被阻塞的操作继续执行。 从用户使用角度来看,网络的读写都是顺序执行的,极大 地简化了编程。
正是 Network+闭包+Goroutine+Channel让Go语言 这么突出,突破了用户在编写大规模系统程序时的局限
库实现
- 完全用Go语言实现, 不依赖其他系统库。
- 模块管理。一个Package可以分散在多个文件里,通过包名整合在一起。支持包层面的初始化操作。
- 接口库如XML、Asn1、JSON、IO库、压缩、加密库等,比较齐全,极大地方便了用户。 支持Unicode。
与其他语言的交互
Cgo 支持C和Go语言编程混合,使得Go语言的扩展 非常容易,让Cgo来做参数和类型转换,直接连接用户的 C函数。
Golang如何实现锁
从操作系统层面硬件层面,可以使用中断来实现锁,软件层面则可以使用信号量。信号量(semaphore, mutext是semaphore的一种)的实现方式有两种:wait的时候忙等待或者阻塞自己。
golang互斥所的两个特性
1.不支持嵌套锁
2.可以一个goroutine lock,另一个goroutine unlock
|
|
sema就是信号量,一个非负数;state表示Mutex的状态。mutexLocked表示锁是否可用(0可用,1被别的goroutine占用),mutexWoken=2表示mutex是否被唤醒,mutexWaiterShift=2表示统计阻塞在该mutex上的goroutine数目需要移位的数值。
atomic.CompareAndSwapInt32(),atomic包是由golang提供的low-level的原子操作封装,操作系统级的锁的实现方案是提供原子操作,然后基本上所有锁相关都是通过这些原子操作来实现,CompareAndSwapInt32()就是int32型数字的compare-and-swap实现。cas(&addr, old, new)的意思是if *addr==old, *addr=new。大部分操作系统支持CAS,x86指令集上的CAS汇编指令是CMPXCHG
Advance Golang
- 引导与初始化
所有 init 函数都在同一个 goroutine 内执行。所有 init 函数结束后才会执行 main.main 函数。 - 内存分配
- TCMalloc小记
mmap 虚拟存储器的相关知识 Golang 编译器支持逃逸分析(escape analysis),它会在编译期通过构建调用图来分析局部变量是否会被外部引用,从而决定是否可直接分配在栈上,你或许见过 “Zero Garbage” 这个说法,其目的就是避免在堆上的分配行为,从而减小垃圾回收压力,提升性能。另外,做性能测试时使用 go test -benchmem
参考资料
- 系统编程语言明日之星-GO
- golang内存分配分析
- 年终盘点!2017年超有价值的Golang文章
- 编写高性能的Go代码的最佳实践
- SOLID Go Design
- The Why of Go
- Rick Hudson - Go GC: Solving the Latency Problem
- How to optimize Go for really high performance
- go-is-not-good
- 对 Go 语言的综合评价
- golang sucks
- Go在谷歌:以软件工程为目的的语言设计
- gopher reading list
- Go知识图谱
- gopherCon china ppt
- GopherCon github
- golang walker
- golang news
- 进击的Golang
- Evolutionary Optimization with Go(GopherCon2017)
- learn golang in n minute
- malloc 背后的系统知识 | Legendtkl
- Golang 垃圾回收剖析 | Legendtkl
- wikipedia泛型
- 《深入解析Go》
- golang中的锁源码实现:Mutex | Legendtkl
- Go by Example
- GitHub - dominikh/go-tools: A collection of tools and libraries for working with Go code, including linters and static analysis
- implementation of golang · GitBook
- 译参考资料: 地道的GO代码 | 鸟窝
- Introduction · 深入解析Go - Introduction · Go-SCP
- GopherCon 2017: Kavya Joshi - Understanding Channels - YouTube channel
- Golang UK Conference 2015 Dean Elbaz Understanding Memory Allocation in Go - YouTube memory allocation
- GOTO 2014 • The Fundamentals of Garbage Collector Performance • Charlie Hunt - YouTube garbage collection
- There is no pass-by-reference in Go | Dave Cheney
Map A map value is a pointer to a runtime.hmap structure.- If a map isn’t a reference variable, what is it? | Dave Cheney map - Understanding Go Interfaces - YouTube interface
- 理解go的反射机制reflection 反射
- 译像牛人一样改进你的Go代码 | 鸟窝
- GitHub - tidwall/evio: Fast event-loop networking for Go
- writing-high-performance-go
- 编写和优化Go代码
- golang中的锁源码实现:Mutex
- golang面试笔试题
- 如果你是一个Golang面试官,你会问哪些问题?
- golang 面试题