一、简介
Go语言的语法简洁到只有几个关键字,便于记忆。而且其编译速度非常快,Go开发者能显著减少等待项目构建的时间。因为Go语言内置并发机制,所以不用被迫使用特定的线程库,就能让软件扩展,使用更多的资源。Go语言的类型系统简单且高效,不需要为面向对象开发付出额外的心智,让开发者能专注于代码复用。Go语言还自带垃圾回收器,不需要用户自己管理内存。让我们快速浏览一下这些关键特性。
二、并发
Go语言对并发的支持是这门语言最重要的特性之一。goroutine 很像线程,但是它占用的内存远少于线程,使用它需要的代码更少。通道(channel)是一种内置的数据结构,可以让用户在不同的 goroutine 之间同步发送具有类型的消息。这让编程模型更倾向于在 goroutine 之间发送消息,而不是让多个 goroutine 争夺同一个数据的使用权。
1、goroutine
goroutine 是可以与其他 goroutine 并行执行的函数,同时也会与主程序(程序的入口)并行执行。在其他编程语言中,你需要用线程来完成同样的事情,而在 Go 语言中会使用一个线程来执行多个 goroutine 。net/http 库直接使用了内置的 goroutine 。每个接收的请求都自动在其自己的 goroutine 里处理。goroutine 使用的内存比线程更少, Go 语言运行时会自动在配置的一组逻辑上调度执行 goroutine 。每个逻辑处理器绑定到一个操作系统线程上(如下图)。这让用户的应用程序执行效率更高,而开发工作量显著减少。
在单一系统线程上执行多个 goroutine
如果想在执行一段代码的同时,并行去做另外一些事情, goroutine 是很好的选择。下面一个简单的例子:
func log(msg string){
... //这里是一些记录日志的代码
}
// 代码里有些地方检测的错误
go log("发生了严重的错误")
关键字 go 是唯一需要去编写的代码,调度 log 函数作为独立的 goroutine 去运行,以便与其他 goroutine 并行执行。这意味着应用程序的其余部分会与记录日志并行执行,通常这种并行执行能让最终yonghu觉得性能更好,就像之前所说的,goroutine 占用的资源更少,所以常常能启动成千上万个 goroutine ,我们后续会更加深入的探讨 goroutine 和并发。
2、通道
通道是一种数据结构,可以让 goroutine 之间进行安全的数据通信。通道可以帮助用户避免其他语言里常见的共享内存访问的问题。
并发最难的部分就是要确保其他并发运行的进程、线程或 goroutine 不会以外修改用户的数据。通道这一模式保证同一时刻只会有一个 goroutine 修改数据。通道用于在几个运行的 goroutine 之间发送数据。在下图中可以看到数据时如何流动的示例。想象一个应用程序,有多个进程需要顺序读取或者修改某个数据,使用 goroutine 和管道,可以为这个过程建立安全的模型。
需要强调的是,通道并不提供跨 goroutine 的数据访问保护机制。如果通过通道传输数据的一份副本,那么每个 goroutine 都持有一份副本,各自对自己的读本做修改是安全的。当传输的是指向数据的指针时,如果读和写是由不同的 goroutine 完成的,每个 goroutine 依旧需要额外的同步操作。
三、Go语言的类型系统
1、类型简单
Go 语言不仅有类似 int 和 string 这样的内置类型,还支持用户定义的类型。在 Go 语言中,用户定义的类型通常包含一组带类型的字段,用于存储数据。不过 Go 语言的类型可以声明操作该类型数据的方法。Go 语言的继承与传统语言不一样,Go 开发者构建更小的类型,然后把这些小类型组合成大类型。
2、Go 接口对一组行为模型
接口用于描述类型的行为。如果一个类型的实例实现了一个接口,意味着这个实例可以执行一组特定的行为。在 Go 语言中,如果一个类型实现了一个接口所有方法,那么这个类型的实例就可以存储在这个接口类型的实例中,不需要额外的声明。
在 Go 语言中,最常使用的接口之一是 io.Reader。这个接口提供了一个简单的方法,用来声明一个类型有数据可以读取。标准库内的其他函数都能理解这个接口。
type Reader interface {
Read(p []byte) (n int, err error)
}
为了实现 io.Reader 这个接口,你只需要实现一个 Read 方法,这个方法接受一个 byte 切片,返回一个整数和可能出现的错误。
实际使用中,这更有利于使用组合来复用代码。Go 语言的整个网络库都使用了 io.Reader 接口,这样可以将程序的功能和不同网络的实现分离。这样的接口用起来有趣、优雅且自由。文件。缓冲区、套接字以及其他数据源都实现了 io.Reader 接口。使用同一个接口,可以高效的操作数据,而不用考虑到底数据来自哪里。
四、内存管理
不当的内存管理会导致程序崩溃或者内存泄露,甚至让整个操作系统崩溃。Go 语言拥有现代化的垃圾回收机制,能帮你解决这个难题。在其他系统语言(如 C 或 C++)中,使用内存前要先分配这段内存,而且使用完毕后将其释放掉。哪怕只做错一件事,都可能导致程序崩溃或者内存泄露、可惜,追踪内存是否还被使用本身就是十分艰难的事情,而要想支持多线程和高并发,更是难上加难。Go 语言把无趣的内存管理jiaogei专业的编译器去做,而让程序员专注于更有趣的事情。