语言特点

简介

Go 是 Google 在 2009 年推出的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,可轻松构建简单、可靠且高效的软件。 不过,为了方便搜索和识别,有时会将其称为 Golang

Go 语言有时候被描述为 21 世纪的 C 语言,Go 从 C 语言继承了相似的表达式语法、控制流结构、基础数据类型、调用参数传值、指针等很多思想。 还有 C 语言一直所看中的编译后机器码的运行效率以及和现有操作系统的无缝适配。

但是在 Go 语言的家族树中还有其它的祖先。

其中一个有影响力的分支来自 Pascal 语言。 然后 Modula-2 语言激发了包的概念。 然后Oberon语言摒弃了模块接口文件和模块实现文件之间的区别。 第二代的 Oberon-2 语言直接影响了包的导入和声明的语法,还有 Oberon 语言的面向对象特性所提供的方法的声明语法等。

Go 语言的另一支祖先,带来了 Go 语言区别其他语言的重要特性,灵感来自于 CSP。 在 CSP 中,程序是一组中间没有共享状态的平行运行的处理过程,它们之间使用管道进行通信和控制同步。

Go 语言的其他的一些特性零散地来自于其他一些编程语言。 比如 iota 语法是从 APL 语言借鉴,词法作用域与嵌套函数来自于 Scheme 语言(和其他很多语言)。

当然 Go 也有很多创新的设计,比如切片为动态数组提供了有效的随机存取的性能,这可能会让人联想到链表的底层的共享机制。 还有 Go 语言新发明的 defer 语句。

自动垃圾回收

从 C 到 C++,从程序性能的角度来考虑,这两种语言允许程序员自己管理内存,包括内存的申请和释放等。 因为没有垃圾回收机制,所以 C/C++ 运行起来速度很快,但是随着而来的是程序员对内存使用上的很谨小慎微的考虑。 因为哪怕一点不小心就可能会导致内存泄露使得资源浪费或者野指针使得程序崩溃等。

为了提高程序开发的速度以及程序的健壮性,Java 和 C# 等高级语言引入了 GC 机制,由语言特性提供垃圾回收器来回收内存。 但是随之而来的可能是程序运行效率的降低。

Go 语言作为一门新生语言,当然不能忽略内存管理这个问题。

更丰富的内置类型

其实作为一种新兴的语言,如果仅仅是为了某种特定的用途那么可能其内置类型不是很多,仅需要能够完成基本功能即可。 但是 Go 语言不仅支持几乎所有语言都支持的简单内置类型(比如整型和浮点型等)外,还支持一些其他的高级类型,比如字典、切片。

函数多返回值

在 C/C++ 中,包括其他的一些高级语言是不支持多个函数返回值的。 但是这项功能又确实是需要的,所以它们一般通过将返回值定义成一个结构体,或者通过函数的参数引用的形式进行返回。

Go 语言不需要那么麻烦,它支持函数多返回值。

错误处理

在传统的 OOP 编程中,为了捕获程序的健壮性需要捕获异常,使用的方法大都是 try-catch。

Go 中的错误处理不需要这样,且 Go 语言中只有 error panic,没有 warn。

但是在当前版本中,Go 处理错误是这样的。

if err != nil{
    // handle err
}

这种错误处理会非常多,被很多人所排斥。不过我觉得还行,起码必须要去处理错误,只是没有一种优雅的方法,且多数人都不愿意去处理错误。

对于 Go 的错误处理一直有人在 建议, 但 提出的建议 并不怎么样。

过分的简单往往是一种负担。

匿名函数和闭包

在 Go 语言中,所有的函数也是值类型,可以作为参数传递。

f := func(x, y int) int {
    return x + y
}

类型和接口

type Bird struct { 
    // ...
} 
func (b *Bird) Fly() { 
    // ...
} 
type IFly interface { 
    Fly() 
} 
func main() { 
    var fly IFly = new(Bird) 
    fly.Fly() 
}

并发编程

Go 语言引入了 goroutine 概念,它使得并发编程变得非常简单。

通过使用 goroutine 而不是裸用操作系统的并发机制,以及使用消息传递来共享内存而不是使用共享内存来通信,并发编程变得更加轻盈和安全。

通过在函数调用前使用关键字 go,即可开启一个协程。

同时,Go 语言实现了 CSP 来作为 goroutine 间的推荐通信方式。 在 CSP 模型中,一个并发系统由若干并行运行的顺序进程组成,每个进程不能对其他进程的变量赋值。 进程之间只能通过一对通信原语实现协作。Go 语言用 channel 这个概念来轻巧地实现了CSP模型。 channel 的使用方式比较接近 Unix 系统中的 pipe 概念,可以方便地进行跨 goroutine 的通信。

反射

这里的反射和 java 中的反射类似,可以用来获取对象类型的相信信息,并动态操作对象。 因为反射可能会对程序的可读性有很大的干扰,所以,在 Go 中只是在特别需要反射支持的地方才实现反射的一些功能。 反射最常见的使用场景是做对象的序列化,例如 encoding/json encoding/xml encoding/gob encoding/binary 等包就大量依赖于反射功能来实现。

而且反射性能不佳,能有其他更好的实现方式就不要用。

语言交互性

这里的交互性主要是和 C 的交互性,之所以这样是因为 Go 语言的开发者是最初贝尔实验室创建Unix系统以及C语言的一般人,包括:

Go 语言中重用了大部份的 C 模块,这里称为 Cgo.Cgo 允许开发者混合编写 C 语言代码 Cgo 工具可以将这些混合的 C 代码提取并生成对于 C 功能的调用包装代码。 开发者基本上可以完全忽略这个Go语言和C语言的边界是如何跨越的。

例如书中一个例子,在Go语言中直接调用了C标准库的puts函数。

package main

/*
#include <stdio.h>
*/
import "C"
import "unsafe"

func main() {
    cstr := C.CString("Hello, world")
    C.puts(cstr)
    C.free(unsafe.Pointer(cstr))
}
powered by Gitbook该文件修订时间: 2020-04-10 10:05:54

results matching ""

    No results matching ""

    results matching ""

      No results matching ""