函数进阶
函数作用域
1.全局变量,在程序整个生命周期都是有效的
2.局部变量:函数内定义/语句块内定义
变量可变性
包内任何变量或者函数都是能访问的。包外的话,首字母大写是可导出的能够被其他包访问或调用。小写表示是私有的,不能被外部的包访问。同一个包内大小写的全局变量或者函数是能被直接调用的。
跨包导入和调用:
1: 导入:2: import (
3: github.comapple_schoollisten1functioncalc"4: )5: 调用:6: calc.Add()7: calc.A
匿名函数
1: func add(a, b int) int {
2: return a + b
3: }4: func test(){5: f1 := add
6: fmt.Printf("type of f1=%T ", f1)
7: }8: func main() {9: test()10: }
1: func test_1() {2: f1 := func(a, b int) int {3: return a + b
4: }5: fmt.Printf("type of f1=%T ", f1)
6: }
defer中使用匿名函数,注意下面两种区别
1: func test_2() {2: var i int = 03: defer fmt.Printf("i=%d ", i) // defer里i=0传进去了4: i = 1005: return
6: }7: >>> i = 08:9: func test_3() {10: var i int = 011: defer func() {12: fmt.Printf("defer i=%d ", i)
13: } ()14: i = 10015: return
16: }17: >>> defer i=100
函数作为参数
1: func add(a, b int) int {
2: return a + b
3: }4:5: func test_c(a, b int32) int32 {6: return a * b
7: }8:9: func sub(a, b int) int {
10: return a - b
11: }12:13: func calc(a, b int,op func(int, int) int) int {14: return op(a, b)
15: }16:17: func test_4() {18: sum := calc(100, 300, add)
19: sub := calc(100, 300, sub)20: su := calc(100, 300, test_c)21: fmt.Printf("sum=%d sub=%d ", sum, sub)22: }23:
闭包
即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。
例子1:
1: package main2: import "fmt"3:4: func add(base int) func(int) int {
5: return func(i int) int {
6: base += i7: return base
8: }9: }10: func main() {11: tmp1:= add(10)
12: fmt.Println(tmp1(1), tmp1(2), tmp1(3))13: tmp2:= add(100)
14: fmt.Println(tmp2(1), tmp2(2), tmp2(3))15: }16: >>> 11 13 1617: 101 103 106
例子2:
1: package main2: import (
3: "fmt"
4: "strings"
5: )6:7: func makeSuffix(suffix string) func(string) string {8: return func(name string) string {9: if !strings.HasSuffix(name, suffix) {10: return name + suffix11: }12: return name13: }14: }15: func main() {16: func1 := makeSuffixFunc(".bmp")
17: func2 := makeSuffixFunc(".jpg")
18: fmt.Println(func1("test"))
19: fmt.Println(func2("test"))
20: }21:22: >>> test.bmp23: test.jpg
用python3来写就是这样(比较容易理解)
1: def makeSuffix(suffix):
2:3: def func(name):4: if not name.endswith(suffix):5: return name + suffix6: return func
7: func = makeSuffix(".bmg")
8: print(func("test"))
例子3:
1: func calc(base int) (func(int) int, func(int) int) {2: add:= func(i int) int {
3: base += i4: return base
5: }6: sub:= func(i int) int {
7: base -= i8: return base
9: }10: return add, sub11: }12:13: func main() {14: f1, f2 := calc(10)15: fmt.Println(f1(1), f2(2))16: fmt.Println(f1(3), f2(4))17: fmt.Println(f1(5), f2(6))18: fmt.Println(f1(7), f2(8))19: }20:21: >>> 11 922: 12 823: 13 724: 14 6
闭包的意义:
返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
在多线程下的闭包的副作用:(了解就行了)
几次的输出结果你会发现不但数值不是固定的,而且居然还会打印出5。本来循环在i=5是就停止了,但是协程搞了鬼,这个后面再讲。1: package main2:3: import (
4: "fmt"
5: "time"
6: )7: func main() {8: for i:=0;i<5;i++ {9: go func(){10: fmt.Println(i)11: } ()12: }13: time.Sleep(time.Second*1)14: }