1. 函数:
go
①. 声明:
func 函数名字 (参数列表) (返回值列表){}
②. 举例:
func add() {}
func add(a int , b int) int {}
func add(a int , b int) (int, int) {}
③. 特点:
a. 不支持重载,一个包不能有两个名字一样的函数.
b. 函数也是一种类型,一个函数可以赋值给变量(这个变量是一个指针指向函数地址).
c. 匿名函数
d. 多返回值
e. type定义新的类型:type addFunc func(int, int) int => 表示函数也是一种类型
④. 函数参数传递方式:
a. 值传递
b. 引用传递
c. 值传递、引用传递,传递给函数的都是变量的副本.值传递是值的拷贝,引用传递是地址(8个字节)的拷贝.
d. 一般来说,地址拷贝更为高效.值拷贝取决于拷贝的对象大小,对象越大,则性能越低.
e. map、slice、chan、指针、interface默认以引用的方式传递.
⑤. 命名返回值的名字:
func calc(a, b int) (sum int, avg int) {
sum = a + b
avg = (a +b) / 2
return
}
⑥. _标识符,用来忽略返回值.
a, _ = add()
_, a = add()
⑦. 可变参数:
func add(arg...int) int {} // 0个或多个参数
func add(a int, arg...int) int {} // 1个或多个参数,a是固定参数(可以有多个固定参数)
a. arg是一个slice(切片).
b. 通过arg[index]依次访问所有参数.
c. 通过len(arg)来判断传递参数的个数.
2 defer:
(1). 概念:
go
①. 当函数返回时,执行defer语句.因此,可以用来做资源清理.
②. 多个defer语句,按先进后出的方式执行(最晚的先执行).
③. defer语句中的变量,在defer声明时就决定了.
④. 举例:
var a int = 111
defer fmt.Println(a) // 第3执行,打印值为111.在defer定义时,是什么值就是什么值.跟后面没关系.
defer fmt.Println("333") // 第2执行,因为先进后出,先入栈后出.
a = 222
fmt.Println(a) // 第1执行
结果:
222
333
111
(2). 用途:
go
①. 关闭文件句柄:
file := open(filename)
defer file.Close()
// 文件操作
②. 锁资源释放:
mc.Lock()
defer mc.Unlock()
// 其他操作
③. 数据库连接释放:
conn := openDatabase()
defer conn.Close()
// 其他操作
3. 内置函数:
①. close:
主要用来关闭channel.
②. len:
用来求长度,如string、array、slice、map、channel.
③. new:
用来分配内存(值类型),如int、struct.返回的是指针.
a := new(int) // 返回一个内存地址
*a = 100
④. make:
用来分配内存(引用类型),如chan、map、slice.
⑤. append:
用来追加元素到数组、slice中.
⑥. panic和recover:
用来做错误处理.
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}() // 匿名函数自调用
func initConfig() (err error) {
return errors.New("init config failed")
}
func main() {
err := initConfig()
if err != nil {
panic(err)
}
}
3.1 new与make的区别:
go
①. new图:
a. new一个[]int的切片 => 第一行
b. new返回一个指向切片的指针(*[]int) => 第二行
c. 这个地址指向一个实际的切片 => 第三行
②. make返回不是一个指针,就是一个切片.
③. 举例:
c := new([]int)
fmt.Println(c) // &[],返回指向切片的指针.
d := make([]int, 3)
fmt.Println(d) // [0 0 0],返回一个切片
// 如果没有这句会报错:panic: runtime error: index out of range.
// 因为new的时候,指针指向一个空的slice,slice没有初始化.
*c = make([]int, 5)
(*c)[0] = 1 // 因为是指针,加*号
d[0] = 2
4. 递归函数:
斐波那契数(前两个数相加等于后一个数):
go
func fab(n int) int {
if n <= 1 {
return 1
}
return fab(n-1) + fab(n-2)
}
func main() {
for i := 0; i < 10; i++ {
n := fab(i)
fmt.Println(n)
}
}
5. 闭包:
一个函数和与其相关的引用环境组合而成的实体.
go
func Adder() func(int) int { // 返回一个函数func(int) int
var x int
return func(d int) int { // 这里必须与定义的返回函数一致
x += d
return x
}
}
func main() {
var f = Adder()
fmt.Print(f(1), " - ") // 1
fmt.Print(f(20), " - ") // 21
fmt.Print(f(300)) // 321
}