Go语言是一门静态类型开发语言。
Go语言最主要的特性如下:
(1)自动垃圾回收
(2)更丰富的内置类型
(3)函数多返回值
(4)错误处理
(5)匿名函数和闭包
(6)类型和接口
(7)并发编程
(8)反射
(9)语言交互性
(一)垃圾回收
对于需要手动管理内存的语言来说,可能引发的一个问题是:如果开发者忘记释放内存,会引发内存泄漏问题。如果方法频繁被调用,会出现内存一直疯涨致使系统内存全部被占用并导致程序崩溃,如果泄露的是系统资源,有可能导致系统崩溃。还可能引发的另外一个问题是:由于指针到处传递而无法确定何时可以释放该指针所指向的内存块。假如代码中某个位置释放了内存,而另外一些地方还在使用指向这块内存的指针,那么这些指针有可能变成了野指针或者悬空指针,对这些指针进行的任何操作都会导致不可预料的后果。
因为C/C++杰出的效率,所以在非常长的时间内都作为服务器系统的主要开发语言。服务器的崩溃也经常是由于不正确的内存和资源管理导致。
为了解决这些问题,出现了内存引用计数的方法,通常被称为智能指针。
到目前为止,内存泄露的最佳解决方案是在语言级别引入自动垃圾回收算法(Garbage Collection,简称GC),所谓垃圾回收,即所有内存分配动作都会被在运行时记录,同时任何对该内存的使用也都会被记录,然后垃圾回收器会对所有已经分配的内存进行跟踪监测,一旦发现有些内存已经不再被任何人使用,就阶段性的回收这些没人用的内存。当然,因为需要尽量最小化垃圾回收的性能损耗,以降低对正常程序执行过程的影响。
由于C++本身过于强大,导致C++中支持垃圾收集变成了一个困难的工作。在C/C++之后出现的新语言,比如JAVA和C#等,基本上都已经自带自动垃圾回收功能。
因为Go语言没有C++强大的指针计算功能,所以有垃圾回收功能,因为垃圾回收功能的支持,开发者无需担心所指向的对象失效问题。我们完全不用考虑何时需要释放之前分配的内存问题,系统会自动帮我们判断,并在合适的时候,比如CPU相对空闲的时候,进行自动垃圾收集工作。
(二)更丰富的内置类型:语言内置特性使开发者不用费事去添加依赖的包。
Go语言支持简单的内置类型(eg.整型、浮点型等)、高级类型(数组、字符串等)
(1)Go语言还内置了对于其他静态类型语言通常用库方式支持的字典类型(map),[为什么要内置map,因为大多数开发者都需要用到这个类型,每次都import太麻烦。]
(2)数组切片(Slice) 数组切片是一种可动态增长的数组。类似c++标准库中的vector。
(三)函数多返回值
目前主流语言除Phthon外基本都不支持函数的多返回值功能。
如果我们想实现多返回值,一般有两种做法,要么专门定义一个结构体用于返回(好几个值)或者以传出参数的方式返回多个结果。
(四)错误处理
Go语言引入了3个关键字用于标准的错误处理流程,这三个关键字分别是defer、panic和recover。相对C++和Java等语言中的一场捕获机制相比,Go语言的错误处理机制可以大量减少代码,而不必一层层添加大量的try-catch语句。
(五)匿名函数和闭包
在Go语言中,所有的函数也是值类型,可以作为参数传递。Go语言支持常规的匿名函数和闭包。
(六)类型和接口
Go语言的类型定义接近于C语言中的结构struct,也沿用了struct关键字。但是不支持继承和重载,只支持最基本的类型组合功能。同样,C++/Java中使用那些复杂的类型系统实现的功能在Go语言中并不会出现无法表现的情况。
Go语言不是简单的对面向对象开发语言作减法,还引入了无比强大的”非侵入式“接口的概念。
(七)并发编程
Go语言引入了goroutine概念,使并发编程变得非常简单,通过使用goroutine而不是裸用操作系统的并发机制以及使用消息传递来共享内存而不是使用共享内存来通信。
通过在函数调用前使用关键字go,便可让该函数以goroutine方式执行,gotoutine是一种比线程更加轻盈、更省资源的协程。Go语言通过系统的线程来多路派遣这些函数的执行,使得每个用go关键字执行的函数可以运行成为一个单位协程。当一个协程阻塞的时候,调度器就会自动把其他协程安排到另外的线程中去执行,从而实现了程序无等待并行化运行,而且调度的开销非常小,一颗CPU调度的规模不下于每秒百万次,这使得我们能够创建大量的goroutine,从而可以很轻松的编写高并发程序,以达目的。
Go语言实现了CSP(通信顺序进程 Communicating Sequential Process)模型来作为goroutine间的推荐通信方式,在CSP模型中,一个并发系统由若干并行运行的顺序进程组成,每个进程不能对其他进程的变量赋值。进程之间只能通过一对通信原语实现协作。Go语言用channel(通道)这个概念来巧合的实现了CSP模型。channel的使用方式比较接近Unix系统中的管道(pipe)概念,可以方便的进行跨goroutine的通信。
另外,由于一个进程内创建的所有goroutine运行在同一个内存地址空间中,因此如果不同的goroutine不得不去访问共享的内存变量,访问前应该先获取相应的读写锁。Go语言标准库中的sync包提供了完备的读写锁功能。
(八)反射
反射是在Java语言出现后迅速流行起来的一种概念。通过反射,你可以获取对象类型的详细信息,并可动态操作对象。反射是把双刃剑,功能强大但代码的可读性并不理想。若非必要,我们并不推荐使用反射。
Go语言的反射实现了反射的大部分功能,但没有像Java语言那样内置类型工厂,故而无法做到像Java那样通过类型字符串创建对象实例。在Java中,你可以读取配置并根据类型名称创建对应的类型,这是一种常见的编程手法,但是在Go语言中并不推荐。
反射最常见的使用场景是做对象的序列化(serialization)。例如,Go语言标准库的encoding/json、encoding/xml、encoding/gob、encoding/binary等包就大量依赖于反射功能来实现。
(九)语言交互性
Go语言可以重用现有C模块,这个功能被命名为Cgo。Cgo既是语言特性,也是一个工具名称。
在Go代码中,可以按Cgo的特性语法混合编写C语言代码,然后Cgo工具可以将这些混合的C代码提前并生成对于C功能的调用包装代码。开发者基本上可以完全忽略这个Go语言和C语言的边界时如何跨越的。
有疑问加站长微信联系(非本文作者)