GO语言特性
并发编程
Go 语言引入了 goroutine,它是 Go 实现快速高效的并发编程的关键。通过调用 go 关键字,就可以让函数以 goroutine 的方式进行运行,也就是以协程为单位进行运行。协程比线程更加的轻量级,也更节省系统资源,这使得我们可以创建大量的 goroutine,从而进行轻松且高质量的并发编程。同时,goroutine 内部采用管道 channel 进行消息传递,从而实现共享内存。
错误处理
Go 语言中的错误处理的哲学和 C 语言一样,函数通过返回错误类型 (error) 或者 bool 类型(不需要区分多种错误状态时)表明函数的执行结果,调用检查返回的错误类型值是否是 nil 来判断调用结果。并引入了 defer 关键字用于标准的错误处理流程,并提供了内置函数 panic、recover 完成异常的抛出与捕捉。
垃圾回收
Go 语言自带垃圾自动回收的功能,让 Go 语言不需要 delete 关键字,也不需要 free() 来释放内存。因此开发者无需考虑何时需要释放之前分配的内存的问题,系统会自动帮我们判断,并在适当的时候进行垃圾处理。垃圾自动回收是 Go 语言的一个特点,也是一大亮点。
多返回值
Go 语言和 Python 一样也支持函数的多返回值功能,这个特性让开发者可以从原来用各种比较别扭的方式返回多个值得痛苦中解脱出来,不需要为了一次返回多个值而专门定义一个结构体。并且每个返回值都有自己的名字,开发者还可以选择具体需要返回的值,只需要使用下划线作为占位符来丢掉不要的返回值即可。
匿名函数
Go 语言支持常规的匿名函数和闭包,开发者可以随意对匿名函数变量进行传递和调用,下面就是一个匿名函数样例:
f := func(x,y int) int {
return x+y
}
Hello,world!
package main
import (
"fmt" //导入fmt包,调用其中的Println()函数
)
func main() {
fmt.Println("Hello,world!")
}
常量
常量使用关键字 const 声明,下面有几个例子:
const limit = 512
const top uint16 = 1421
const Pi float64 = 3.1415926
const x,y int = 1,3 //多重赋值
Go 的常量定义可以限定常量类型,但不是必需的。如果定义常量时没有指定类型,那么该常量就是无类型常量,也叫字面常量。
当需要设置多个常量的时候,不必重复使用 const 关键字,可以使用以下语法:
const (
Cyan = 0
Black = 1
White = 2
)
变量
变量是所有语言最基本和最重要的组成部分。Go 语言引入了关键字 var 对变量进行声明,也可以使用 := 来对变量直接进行初始化,Go 编译器会自动推导出该变量的类型,这大大的方便了开发者的工作。但是需要注意的是 := 左侧的变量不能是已经被声明过的,否则会导致编译器错误。
以下是 Go 声明和初始化变量的各种方法:
var a int
var b string
var c float64
var d [5] int //数组
var e [] int //数组切片
var f * int //正确
var v1 int = 5 //正确
var v2 = 5 //正确,编译器自动推导出V2类型
v3 := 5 //正确,编译器自动推导出V3的类型
i := 2
j := 3
i, j = j, i //交换i和j的值,此时i == 3,j == 2
数据类型
整型
Go 语言提供了 11 种整型。在 Go 语言中可以通过 unsafe.Sizeof 函数查看类型的字节长度。
import (
"fmt"
"unsafe"
)
func main() {
a := 12
fmt.Println("length of a: ", unsafe.Sizeof(a))
}
以上代码中,首先声明了目前的源文件属于 main 包,然后导入了 fmt 和 unsafe 包,fmt 包用于格式化字符串,unsafe 包含了用于获取 Go 语言类型信息的方法。然后在 main() 函数中,声明整型变量,并通过 unsafe.Sizeof 方法获取该类型的字节长度。
输出:
length of a: 8
浮点型
Go 语言提供了两种浮点类型和两种复数类型float32、float64、complex32、complex64。
布尔类型
Go 语言提供了内置的布尔值 true 和false。Go 语言支持标准的逻辑和比较操作,这些操作的结果都是布尔值。值得注意的地方是可以通过 !b 的方式反转变量 b 的真假。需要注意的是布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换。
var a bool
a = true
b := (2 == 3) //b也会被推导为bool类型
//错误示范
var b bool
b = 1 //编译错误
b = bool(1) //编译错误
字符串
Go 语言中字符串的可以使用双引号 (") 或者反引号 (`) 来创建。双引号用来创建可解析的字符串字面量,所谓可解析的是指字符串中的一些符号可以被格式化为其他内容,如 \n 在在输出时候会被格式化成换行符,如果需要按照原始字符输出必须进行转义。而反引号创建的字符串原始是什么样,那输出还是什么,不需要进行任何转义。以下是几个例子:
t1 := "\"hello\"" //内容: "hello"
t2 := `"hello"` //内容:和t1一致
t3 := "\u6B22\u8FCE" //内容:欢迎
数组
Go 语言的数组是一个定长的序列,其中的元素类型相同。多维数组可以简单地使用自身为数组的元素来创建。数组的元素使用操作符号 [ ] 来索引,索引从 0 开始,到 len(array)-1 结束。数组使用以下语法创建:
[length]Type[N]Type{value1, value2, ..., valueN}[...]Type{value1, value2, ..., valueN}
如果使用了 ...(省略符)操作符,Go 语言会为我们自动计算数组的长度。在任何情况下,一个数组的长度都是固定的并且不可修改。数组的长度可以使用 len() 函数获得。由于数组的长度是固定的,因此数组的长度和容量都是一样的,因此对于数组而言 cap() 和 len() 函数返回值都是一样的。数组也可以使用和切片一样的语法进行切片,只是其结果为一个切片,而非数组。同样的,数组也可以使用 range 进行索引访问。
切片
一般而言,Go 语言的切片比数组更加灵活,强大而且方便。数组是按值传递的(即是传递的副本),而切片是引用类型,传递切片的成本非常小,而且是不定长的。而且数组是定长的,而切片可以调整长度。创建切片的语法如下:
make([ ]Type, length, capacity)make([ ]Type, length)[ ]Type{}[ ]Type{value1, value2, ..., valueN}
内置函数 make() 用于创建切片、映射和通道。当用于创建一个切片时,它会创建一个隐藏的初始化为零值的数组,然后返回一个引用该隐藏数组的切片。该隐藏的数组与 Go 语言中的所有数组一样,都是固定长度,如果使用第一种语法创建,那么其长度为切片的容量 capacity;如果是第二种语法,那么其长度记为切片的长度 length。一个切片的容量即为隐藏数组的长度,而其长度则为不超过该容量的任意值。另外可以通过内置的函数 append() 来增加切片的容量。