golang语言 内置函数、控制流
len 和 cap
调用 实参类型 结果
len(s) [n]T, *[n]T 数组长度(== n)
[]T 切片长度
chan T 信道缓存中元素队列的长度
map[K]T 映射长度(已定义键的数量)
string type 字符串的字节长度
cap(s) [n]T, *[n]T 数组长度(== n)
[]T 切片容量
chan T 信道缓存容量
s为 nil 值的切片、映射或信道,len(s)==0
s为 nil 值的切片或信道,cap(s)==0。
若 s 为字符串常量,则表达式 len(s) 即为 常量。 若 s 的类型为数组或数组指针,且表达式 s 不包含信道接收 或函数调用,则表达式 len(s) 与 cap(s) 即为常量,在这种用情况下, s 不会被求值。否则,len 与 cap 的调用不为常量,且 s 会被求值。
const (
c1 = imag(2i) // imag(2i) = 2.0 is a constant
c2 = len([10]float64{2}) // [10]float64{2} contains no function calls
c3 = len([10]float64{c1}) // [10]float64{c1} contains no function calls
c4 = len([10]float64{imag(2i)}) // imag(2i) is a constant and no function call is issued
c5 = len([10]float64{imag(z)}) // invalid: imag(z) is a (non-constant) function call
c6 = len([10]float64{x}) // 10
)
var z complex128
var x float64 = 3.0
new
type S struct { a int; b float64 }
new(S) 将动态分配内存、初始化为零值(a=0,b=0.0)并返回类型为 *S 的包含内存地址的值。
var p *[]int = new([]int) // p != nil *p == nil,没有底层数组
p := *new([]int) // p == nil
new(File) 和 &File{} 是等价的
make
切片、映射与信道为无需使用 new 来间接额外分配的引用类型。内建函数 make 接受的类型 T 必须为切片、映射或信道类型,可选地跟着一个特殊类型的表达式列表。它返回类型为 T (而非 *T)的值。其内存用零值来初始化。
调用 类型 T 结果
make(T, n) slice 类型为T,长度为n,容量为n的切片
make(T, n, m) slice 类型为T,长度为n,容量为m的切片
make(T) map 类型为T的映射
make(T, n) map 类型为T,初始空间为n个元素的映射
make(T) channel 类型为T的同步信道
make(T, n) channel 类型为T,缓存大小为n的异步信道
s := make([]int, 10, 100) // len(s) == 10,cap(s) == 100 的切片
c := make(chan int, 10) // 缓存大小为10的信道
m := make(map[string]int, 100) // 初始空间为100个元素的映射
n必须为能表示为int的值,若 n 在运行时为负值或大于 m, 就会引发panic
复数操作
complex(realPart, imaginaryPart floatT) complexT
real(complexT) floatT
imag(complexT) floatT
若这些函数的操作数均为常量,则返回值亦为常量
z == complex( real(z), imag(z) )
var a = complex(2, -2) // complex128
const b = complex(1.0, -1.4) // untyped complex constant 1 - 1.4i
x := float32(math.Cos(math.Pi/2)) // float32
var c64 = complex(5, -x) // complex64
var s int = complex(1, 0) // untyped complex constant 1 + 0i can be converted to int
_ = complex(1, 2<<s) // illegal: 2 assumes floating-point type, cannot shift
var rl = real(c64) // float32
var im = imag(a) // float64
const c = imag(b) // untyped constant -1.4
_ = imag(3 << s) // illegal: 3 assumes complex type, cannot shift
for
任何For子句的元素都可为空,但除非只有一个条件,否则分号是必须的。 若缺少条件,则它等价于 true。
for cond 等价于 for ; cond ;
for true 等价于 for ; true ; 等价于 for 等价于 for ; ;
for a := 0 ; ; { // 这个a被声明在外层隐式代码块中
a := a // 内层显式代码块
}
range
range右边部分叫做range表达式,
range表达式如果不是信道,那么for i , _ := range s 等价于 for i := range s,
range表达式如果是信道,左边只能有一个值
在for语句之外声明的迭代变量,其值为最后一次迭代的值
for range ch {} // 排空一个channel
for range str {cnt++} // 统计unicode字符
for i, v := range arr { // arr会复制
a := 3
fmt.Println(&i, &v, &a) // i 和 v 的地址不变,a地址会变
}
x是数组、数组指针或切片,第一个迭代变量是下标,从0开始递增到 len(x)-1,
nil值的切片会迭代0次,
nil值的数组指针,若第二个迭代变量被忽略或舍弃,迭代 len(数组) 次,否则panic
x是字符串,第一个迭代变量是当前unicode码点第一个字节的下标,
第二个迭代变量是rune类型的unicode码点值,
若遇到无效的unicode码点,第一个迭代变量下次加1,第二个迭代变量为0xFFFD,
x是map,迭代顺序随机,map为nil迭代次数为0,
迭代时删除了未迭代到的项,该项之后不会被迭代到
迭代时创建的新项可能会被迭代,也可能不会
x是信道,会迭代到信道被关闭,nil值的信道会一直阻塞
if
a := 0
if a := 1; ... { // 外层隐式代码块 可选的初始化语句,只能有一句
a := 2 // 内层显式代码块
fmt.Println(a) // 2
}else if b := 2; ... { // else if 也可以初始化 并且可以再次初始化a
fmt.Println(a) // 1
}
fmt.Println(a) // 0
func Foo() (err error) {
if err := Bar(); err != nil { return } // 局部变量屏蔽了命名返回值
return
}
switch
接受可选的初始化语句
没有条件的switch相当于switch true,
没有分支的switch是个空操作
case 可以为变量、表达式或函数,可以用逗号分隔,
执行到当前case时才会去求case的值,否则跳过
默认不会执行下一个case,fallthrough表示执行下一个case,最后一个分支不能有fallthrough,fallthrough必须为分支内的最后一条语句,if true { fallthrough }是非法的
最多只能有一个default,可以出现在任何位置。 能fallthrough 进/出 default
switch表达式要有确定的类型,所以不能switch nil
switch 1 case int8(1) //报错 目测是switch 1确定了1的类型
switch int8(1) case 1 //ok 目测是case1没有确定1的类型
switch int8(1) case int(1) //报错
标签语句
可作为 goto、break 或 continue 语句的目标,标签语句至少要被使用一次
goto
可在标签的前面或后面,但不能在标签所处的代码块之外,
也不能在变量声明之前,goto到该变量的作用域里,例如
goto A
a := 1
A:
break
用于for、switch、select中
OuterLoop:
for i = 0; i < n; i++ {
for j = 0; j < m; j++ {
switch a[i][j] {
case item:
break OuterLoop // 跳出OuterLoop后面的for循环
}
}
}
continue
用于for中
RowLoop:
for y, row := range rows {
for x, data := range row {
continue RowLoop
}
}