简要介绍 Go 语法及特性。原文:go-lang-cheat-sheet
目录
- 基础语法
- 运算符
- 算术运算符
- 比较运算符
- 逻辑运算符
- 其他
- 声明
- 函数
- 函数作为值和回调使用
- 可变参数函数
- 内置类型
- 类型转换
- package
- 流程控制结构
- 条件判断(if)
- 循环(for)
- 多条件分支(switch)
- array, slice, range
- array
- slice
- array 和 slice 的操作函数
- map
- 结构体
- 指针
- 接口
- 结构体和接口的组合嵌入
- Errors
- 并发
- goroutine
- channel
- channel 开发原则
- 输出
- 代码片段
- Http-Server
前言
参考
文中大部分代码都摘抄自 A Tour of Go,对新手来说是很好的参考资料。
Go 特性
- 命令式编程
- 静态类型
- 类 C 语法(括号使用频率更少 & 无需分号),类 Oberon-2 的语法结构
- 代码能编译为本地可执行文件(无需 JVM 类的虚拟机)
struct
和method
取代类的概念- 接口
- 类型组合 取代显式继承
- 有头等函数
- 有回调函数
- 函数可有多个返回值
- 保留指针,但不能直接参与算术运算
- 内置并发原语:
goroutine
和channel
基础语法
Hello World
文件 hello.go
:
1 | package main |
运行:$ go run hello.go
运算符
算术运算符
运算符 | 描述 |
---|---|
+ |
加 |
- |
减 |
* |
乘 |
/ |
除 |
% |
取余 |
& |
按位与 |
` | ` |
^ |
按位异或 |
&^ |
按位清除(AND NOT) |
<< |
左移 |
>> |
右移 |
&^
即是 AND NOT(x, y) = AND(x, NOT(Y))
,如:
1 | package main |
比较运算符
运算符 | 描述 |
---|---|
== |
相等 |
!= |
不等 |
< |
小于 |
<= |
小于等于 |
> |
大于 |
>= |
大于等于 |
逻辑运算符
运算符 | 描述 |
---|---|
&& |
逻辑与 |
¦¦ | 逻辑或 |
! |
取反 |
其他
运算符 | 描述 |
---|---|
& |
寻址(生成指针) |
* |
获取指针指向的数据 |
<- |
向 channel 中发送 / 接收数据 |
声明
与 C 不同,类型放在标识符后面:
1 | var foo int // 无初值的声明 |
函数
1 | // 最简单的函数 |
函数作为值和回调使用
1 | func main() { |
可变参数函数
1 | func main() { |
内置类型
1 | bool |
类型转换
1 | var i int = 42 |
package
- package 在源文件开头声明
- main package 才是可执行文件
- 约定:package 名字与 import 路径的最后一个单词一致(如导入 math/rand 则 package 叫 rand)
- 大写开头的标识符(变量名、函数名…):对其他 package 是可访问的
- 小写开头的标识符:对其他 package 是不可见的
流程控制结构
if
1 | func main() { |
Loops
1 | // Go 语言中循环结构只有 for,没有 do、while、until、foreach 等等 |
switch
1 | // switch 分支语句 |
Arrays, Slices, Ranges
Arrays
1 | var a [10]int // 声明长度为 10 的 int 型数组,注意数组类型 = (元素类型 int,元素个数 10) |
slices
1 | var a []int // 声明 slice,相当于声明未指定长度的数组 |
数组和 slice 的操作函数
1 | // 迭代数组或 slice |
map
1 | var m map[string]int |
结构体
Go 语言中没有 class 类的概念,取而代之的是 struct,struct 的方法对应到类的成员函数。
1 | // struct 是一种类型,也是字段成员的集合体 |
匿名结构体
使用 map[string]interface{}
开销更小且更为安全。
1 | point := struct { |
指针
1 | p := Vertex{1, 2} // p 是一个 Vertex |
接口
1 | // 声明接口 |
结构体和接口的组合嵌入
1 | // 实现 ReadWriter 的类型要同时实现了 Reader 和 Writer 两个接口 |
Errors
Go 中没有异常处理机制,函数在调用时在有可能会产生错误,可返回一个 Error
类型的值,Error
接口:
1 | type error interface { |
一个可能产生错误的函数:
1 | func doStuff() (int, error) { |
并发
goroutine
goroutine(协程)是轻量级的线程(Go runtime 自行管理,而不是操作系统),代码 go f(a, b)
就开了一个运行 f
函数的协程。
1 | func doStuff(s string) { |
Channels
1 | ch := make(chan int) // 创建类型为 int 的 channel |
channel 开发原则
向 nil channel 写数据将卡死,一直阻塞
从 nil channel 读数据将卡死,一直阻塞
向已关闭的 channel 写数据将造成 panic
1
2
3
4
5
6
7
8package main
func main() {
truevar c = make(chan string, 1)
truec <- "Hello, World!"
trueclose(c)
truec <- "Hello, Panic!"
}运行:
从已关闭的 channel 读数据将返回零值
1
2
3
4
5
6
7
8
9
10
11package main
func main() {
truevar c = make(chan int, 2)
truec <- 1
truec <- 2
trueclose(c)
truefor i := 0; i < 3; i++ {
truetrueprintln(<-c)
true}
}运行:
输出
1 | fmt.Println("Hello, 你好, नमस्ते, Привет, ᎣᏏᏲ") // 最基本的输出,会自动加一个换行 |
代码片段
HTTP Server
1 | package main |
运行:
总结
上边十七个知识点简要概括了常见语法,可复习使用,但涉及到的细节不多,细读《Go 程序设计语言》 才是。