杂项
- iota 值在枚举中从0开始逐行增加,即使有的行无iota也会增加
- go的指针、数组和切片定义中,
*,[...],[] Type
定义格式,特殊符号要放在类型前面,与C/Java不同 - fmt.Printf中,%T类型可以打印给出变量的类型,包括函数
基础数据类型与流程控制
数组与切片
- go不允许指针直接参与运算,但可以返回本地变量的指针,原理是返回时将局部变量分配到堆上,这一机制称为“栈逃逸”。
- 数组与切片
// 创建
arr := [...]int{1, 2, 3} // 数组一旦创建就是定长的
arr2 := [10]int{1, 2, 3}// 可以显式指定长度
slice := []int{1, 2, 3} // 切片类型在打印时不显示长度,因其是不定长的
fmt.Println(arr, slice, reflect.TypeOf(arr), reflect.TypeOf(arr2), reflect.TypeOf(slice))
// 显示结果为:[1 2 3] [1 2 3] [3]int [10]int []int
// 访问 : 除了下标访问外,数组和切片
for i, v := range slice/*arr2*/ {
fmt.Println(i, v)
}
- 切片创建的方式
- 除上述创建方法外,所有对数组的切片操作(带:)生成的结果都是切片
- 使用内建的make方法创建切片
// make使用方法:make(type,len[,cap]) a_s1 := make([]int, 10, 15)
- 切片支持的操作
- 内置函数len ()返回切片长度。
- 内置函数cap ()返回切片底层数组容量。
- 内置函数a ppend() 对切片追加元素。
- 内置函数copy ()用于复制一个切片。
map
创建方法:
m1 := map[string]int{"a": 1, "b": 2}
:显式指定或大括号内为空m2 := make(map[string]int[, 10])
:make创建
支持的操作方法:
- 用中括号访存
- 用range访问每个k,v,但不保证顺序
- 用
delete(map,key)
删除 - 用len()返回键值对数量
注意:
- 标准map不是线程安全的,并发安全的map 可以使用标准包sync 中的map 。
- map返回的是view,不能直接修改map value中某个元素的值,要整个替换???如果需要修改map值,要么整个赋值,要么传指针
switch
- switch后可以接一个初始化语句
- case可以接多个值,用逗号分隔
- fallthrough关键字可以跳过当前的case/default表达式,直接执行下一个case/default语句
for
go只支持一种循环,即for,有多种用法
for init; condition; post { }
:三段式的forfor condition { }
:类似whilefor { }
:死循环for index[,value] := Iterable{}
:用于遍历很多可迭代结构
函数
定义结构:
func funcName (param-list) (result- list) {
function - body
}
// 单返回值list的括号可省略
- 支持有名的返回值:
func add (a, b int) (sum int)
,相当于在函数中加了一个var sum int
- 不支持:默认参数,函数重载
- 实参到形参的传递永远是值拷贝,需要修改要用指针
- Go 函数支持不定数目的形式参数,不定参数声明使用param … . type 的语法格式,其中
- 所有的不定参数类型必须是相同的。
- 不定参数必须是函数的最后一个参数。
- 不定参数名在函数体内相当于切片,对切片的操作同样适合对不定参数的操作
- 切片可以作为参数传递给不定参数,切片名后要加上"…",但数组不可以作为不定参数的实参
- 形参为不定参数的函数和形参为切片的函数类型不相同
defer
defer可以注册延迟调用,这些调用以先进后出( FILO )的顺序在函数返回前被执行,类似于finally语句,defer 常用于保证一些资源最终一定能够得到回收和释放。
func FuncFunc() {
slice := []int{1, 2, 3, 4}
array := [...]int{1, 2, 3, 4}
defer func() {
println("defer 1")
}()
multiArg(slice...)
defer func(arg int) {
fmt.Println("defer 2 with arg :", arg)
}(123)
defer multiArg(array[:]...)
}
注意:
- defer 后面必须是函数或方法的调用,不能是语句
- defer 函数的实参在注册时通过值拷贝传递进去
- 主动调用os.Exit( int) 退出进程时, defer 将不再被执行
panic和recover
这两个内置函数用来处理Go 的运行时错误( runtime errors ) 。panic 用来主动抛出错误, recover 用来捕获panic 抛出的错误。
go并发
- 对未关闭的channel进行range操作会产生死锁