Go, 互联网时代的C语言

来源:互联网 发布:最好的win10优化工具 编辑:程序博客网 时间:2024/06/03 17:20

Go语言, 号称互联网时代的C语言。 它从一开始,就适合服务端的开发。
下面具体叙述Go语言为什么适合服务端的开发。

GO 产生的背景

天时

从 2005 年开始,时钟速率的增长和晶体管数量的增长已不再同步。由于处理器材料的物理性质限制,时钟速率已停止增长(甚至下降),处理器制造商开始将更多执行单元(核心)封装到单个芯片(插槽)中。这一趋势(似乎能够在可预见的未来继续保持)已开始给应用程序开发和编程语言开发社区带来越来越大的压力. 高效地利用可用 CPU 核心的惟一方法就是使用并行性。

在应用程序开发方面,基于线程的并发编程是实现并行性的主导机制。
但线程编程存在本质上的困难:

  • 共享对象的竞争问题。
  • 在使用锁的时候,如果不谨慎,容易造成死锁。
  • C标准库的API一般不是线程安全的。
  • 多线程程序很难调试。

所有,基于线程的编程模型不是多核时代的最佳选择.
我们需要更合适的并发模型。

地利

语言层面支持并发模型的, 暂时只有GO和Erlang.

许式伟认为

Erlang的困难之处在于它是FP语言. 我们缺乏深入人心的FP编程理论。我们并不了解FP“数据结构”学。这是Erlang语言无法逾越的门槛,决定了它只能是小众化语言。

在Baidu上搜索“招聘+erlang”, 相关结果约20,300个。
搜索”招聘+go“, 相关结果约1,240,000个。
我个人认为,许式伟的看法是对的。

人和

Go语言之父Rob Pike 这样说

在那一个小时的演讲中,我们大概听到了约35种计划中的新特性。当然实际上还有更多,
这时候,我问了自己一个问题:C++委员会真的认为C++的特性还不够多?当然,不同于Ron的玩笑,简化这门语言必是一门更大的成就!

Go语言社区吸引了大量程序员的参与, 截至2015-10-29日

社区活跃

https://golang.org/AUTHORS 统计,核心提交者有556人。

有人用BigQuery查询github的结果:

【图2】统计从2014年05月1日起到2015年8月8号,各种语言创建的repos数排名。
限定条件:fork数>3;repos大于20MB

从搜索引擎结果看,国内已经有很多公司在使用Go。 包括百度,阿里,豆瓣,陌陌等

语言的特点

Rob Pike 说

在那一个小时的演讲中,我们大概听到了约35种计划中的新特性。当然实际上还有更多。这时候,我问了自己一个问题:C++委员会真的认为C++的特性还不够多?当然,不同于Ron的玩笑,简化这门语言必是一门更大的成就!也许这很可笑,但是请把这个想法记在心里。

类C的语法

slice 和 array 的基本操作

arr := [5]int{1, 2, 3, 4, 5}slice := arr[3 : 5] //  slice:[4, 5]slice[0] = 0        // slice:[0, 5]fmt.Println(slice)fmt.Println(arr)

输出结果是

[0 5][1 2 3 0 5]

对Go的Slice进行Append的一个坑

func main() {    arr1 := [5]int{1, 2, 3, 4, 5}    slice1 := arr1[1:2]    slice1 = append(slice1, 6, 7, 8)    fmt.Println("slice1:", slice1)    fmt.Println("arr1:", arr1)    arr2 := [5]int{1, 2, 3, 4, 5}    slice2 := arr2[1:3]    slice2 = append(slice2, 6, 7, 8)    fmt.Println("slice2:", slice2)    fmt.Println("arr2:", arr2)}

输出结果是

slice1: [2 6 7 8]arr1: [1 2 6 7 8] //神奇地,原数组被改变了slice2: [2 3 6 7 8]arr2: [1 2 3 4 5] //一切正常

interface

type geometry interface {    area() float64    perim() float64}type rect struct {    width, height float64}type circle struct {    radius float64}func (r rect) area() float64 {    return r.width * r.height}func (r rect) perim() float64 {    return 2*r.width + 2*r.height}func (c circle) area() float64 {    return math.Pi * c.radius * c.radius}func (c circle) perim() float64 {    return 2 * math.Pi * c.radius}func measure(g geometry) {    fmt.Println(g)    fmt.Println(g.area())    fmt.Println(g.perim())}func main() {    r := rect{width: 3, height: 4}    c := circle{radius: 5}    measure(r)    measure(c)}

Go语言采用的是“非侵入式接口”.

Goroutines

一个Go例程就是一个和其它Go例程在同一地址空间里但却独立运行的函数。

f("hello", "world") // f runs; we waitgo f("hello", "world") // f starts runningg() // does not wait for f to return

就像是在shell里使用 & 标记启动一个命令。

Go例程不是线程, 很像线程,但比线程更轻量。
一个程序里产生成千上万个Go例程很正常。

多个例程可以在系统线程上做多路通信。

当一个Go例程阻塞时,所在的线程会阻塞,但其它Go例程不受影响。

Channels

Do not communicate by sharing memory; instead, share memory by communicating

通道是类型化的值,能够被Go例程用来做同步或交互信息。

timerChan := make(chan time.Time)go func() {    time.Sleep(deltaT)    timerChan <- time.Now() // send time on timerChan}()// Do something else; when ready, receive.// Receive will block until timerChan delivers.// Value sent is other goroutine's completion time.completedAt := <-timerChan

Select

这select语句很像switch,但它的判断条件是基于通信,而不是基于值的等量匹配。

select {case v := <-ch1:    fmt.Println("channel 1 sends", v)case v := <-ch2:    fmt.Println("channel 2 sends", v)default: // optional    fmt.Println("neither channel was ready")}

以软件工程为目的的语言设计

  • 静态类型语言,直接编译成机器码。不依赖glibc版本,基本没有链接动态库的问题
  • 内置强大的工具。Go语言里面内置了很多工具。社区也实现了很多有用的插件。
    • gofmt, 自动化格式化代码。
    • gocode, 代码自动补全
    • go-def, 代码查找时的自动跳转,如查看函数或结构体的定义。
    • gotags, 显示当前文件包含哪些函数定义,结构体定义
  • 内置runtime,支持垃圾回收,内置性能调优工具。
  • 丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大
  • 语言层面支持并发

参考文献

  • Go, 互联网时代的C语言
  • 多核 CPU 和它们带来的并发性改变
  • Go语言之父谈Go:大道至简
  • 并发不是并行
原创粉丝点击