go get:获取远程包(需提前安装git或hg)
go run:直接运行程序
go build:测试编译,检查是否有编译错误
go fmt:格式化源码
go install:编译包文件并编译整个程序
go test:运行测试文件
go doc:查看文档
go程序的一般结构:
go程序是通过package来组织的
只有package名称为main的包可以包含main函数
一个可执行程序有且仅有一个main包
通过import关键字来导入其他非main包
通过const关键字来进行常量的定义
通过在函数体外部使用var关键字来进行全局变量的声明与福祉
通过type关键字来进行结构(struct)或接口(interface)的声明
通过func关键字来进行函数的声明
go语言中,使用大小写来决定该常量,变量,类型,接口,结构或函数,是否可以被外部包所调用
根据约定:函数名首字母小写为private,函数名首字母大写为public
单个变量的声明与赋值:
变量的声明格式:var <变量名称> <变量类型>
变量的赋值格式:<变量名称> = <表达式>
声明的同时赋值:var <变量名称> [变量类型] = <表达式>
多个变量的声明与赋值:
全局变量的声明可使用var()的方式进行简写
全局变量的声明不可以省略var,但可使用并行方式
所有变量都可以使用类型推断
局部变量不可以使用var()的方式简写,只能使用并行方式
常量的定义
常量的值在编译时就已经确定
常量的定义格式与变量基本相同
等号右侧必须是常量或者常量表达式
常量表达式中的函数必须是内置函数
判断语句if
条件表达式没有括号
支持一个初始化表达式(可以是并行方式)
左大括号必须和条件语句或else在同一行
支持单行模式
初始化语句中的变量为block级别,同时隐藏外部同名变量
循环语句for:
go只有for一个循环语句关键字,但支持3种形式
初始化和步进表达式可以是多个值
条件语句每次循环都会被重新检查,因此不建议在条件语句中使用函数,尽量提前计算好条件并以变量或常量代替
左大括号必须和条件语句在同一行
选择语句switch:
可以使用任何类型或表达式作为条件语句
不需要写break,一旦条件符合自动终止
如希望继续执行下一个case,需使用fallthrough语句
支持一个初始化表达式(可以是并行方式),右侧需跟分号
左大括号必须和条件语句在同一行
数组array:
定义数组的格式:var <varName> [n]<type> , n>=0
数组长度也是类型的一部分,因此具有不同长度的数据为不同类型
注意区分指向数组的指针和指针数组
数组在go中为值类型
数组之间可以使用==或!=进行比较,但不可以使用<或>
可以使用new来创建数组,此方法返回一个指向数组的指针
go支持多维数组
切片slice:
其本身并不是数组,它指向底层的数组
作为变长数组的替代方案,可以关联底层数组的局部或全部
为引用类型
可以直接创建或从底层数组获取生产
使用len()获取元素个数,cap获取容量
一般使用make()创建
如果多个slice指向相同底层数组,其中一个的值改变会影响全部
make([]T,len,cap)
其中cap可以省略,则和len的值相同
len表示存数的元素个数,cap表示容量
reslice:
reslice时索引以被slice的切片为准
索引不可以超过被slice的切片的容量cap()值
索引越界不会导致底层数组的重新分配而是引发错误
append:
可以在slice尾部追加元素
可以将一个slice追加在另一个slice尾部
如果最终长度未超过追加到slice的容量则返回原始slice
如果超过追加到的slice的容量则将重新分配数组并拷贝原始数据
map:
类似其他语言中的哈希表或者字典,以key-value形式存储数据
key必须是支持==或!=比较运算的类型,不可以是函数,map或slice
map查找比线性搜索快得多,但比使用索引访问数据的类型慢100倍
map使用make()创建,支持:=这种简写方式
make([keyType]valueType,cap),cap表示容量,可省略
超出容量时会自动扩充,但尽量提供一个合理的初始值
使用len()获取元素个数
键值对不存在时自动添加,使用delete()删除某键值对
使用for range对map和slice进行迭代操作
函数function:
go函数不支持嵌套,重载和默认参数
支持以下特性:
无需声明原型,不定长度变参,多返回值,命名返回值参数,匿名函数,闭包
定义函数关键字func,且大括号不能另起一行
函数也可以作为一种类型使用
defer:
执行方式类似其他语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
及时函数发生严重错误也会执行
支持匿名函数的调用
常用于资源清理,文件关闭,解锁,以及记录时间等操作
通过与匿名函数配合可在return之后修改函数计算结果
如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即以及获得了拷贝,否则则是引用某个变量的地址
go没有异常机制,但有panic/recover模式来处理错误
panic可以在任何地方引发,但recover只有在defer调用的函数中有效
结构struct:
go中的struct与C中的struct非常相似,并且go没有class
使用type <name> struct{}定义结构,名称遵循可见性规则
支持指向自身的指针类型成员
支持匿名结构,可用做成员或定义成员变量
匿名结构也可用用于map值
可用使用字面值对结构进行初始化
允许直接通过指针来读写结构成员
相同类型的成员可进行直接拷贝赋值
支持==与!=比较运算符,但不支持<或>
支持匿名字段,本质上是定义了以某个类型名为名称的字段
嵌入结构作为匿名字段看起来像继承,但不是继承
可以使用匿名字段指针
方法method:
go中虽没有class,但依旧有method
通过显示说明receiver来实现与某个类型的组合
只能为同一个包中的类型定义方法
receiver可以是类型的值或者指针
不存在方法重载
可以使用值或指针来调用方法,编译器会自动完成转换
从某种意义上来说,方法是函数的语法糖,因为receiver其实就是方法所接受的第1个参数
如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
类型别名不会拥有底层类型所附带的方法
方法可以调用结构中的非公开字段
接口interface
接口是一个或多个方法签名的集合
只要某个类型拥有该接口的所有方法签名,即算实现该接口,无需显示声明实现了哪个接口,这成为structural typing
接口只有方法声明,没有实现,没有数据字段
接口可以匿名嵌入其他接口,或嵌入到结构中
将对象赋值给接口时,会发生拷贝,而接口内部存储的是指向这个复制品的指针,既无法修改复制品的状态,也无法获取指针
只有当接口存储的类型和对象都为nil时,接口才等于nil
接口调用不会做receiver的自动转换
接口同样支持匿名字段方法
接口也可以实现类似OPP中的多态
空接口可以作为任何类型数据的容器