美文网首页
第四节函数

第四节函数

作者: barriers | 来源:发表于2019-12-23 19:12 被阅读0次

1.1函数

1.go函数不支持嵌套、重载和默认参数;
2.但支持以下特性:
无需声明原型、不定长度变参、多返回值、命名返回值参数、匿名函数、闭包;
3.定义函数使用关键字func,且左大括号不能另起一行;
4.函数也可以作为一种类型使用;

当有输入值和输出值时,必须对类型进行限制,如下
1.传入参数当类型都一样时,也可以用a,b int来对参数进行限制;
2.返回参数可以用int, string限制类型,当类型一样时,也可以用a,b int限制,当用a,b int这种时,因为相当于在程序开始就定义了a,b两个变量,所以第一次使用a和b时直接就可以用=而不是:=

func A(a int, b int) (int, int,int){

}

func A(a, b int) (a,b,c int){

}

不定长参数,当传入多个相同类型的变量时,可以用一个变量 ...接类型进行表示,如a ...int(相当于传入了一个slice);
不定长参数必须要放在参数最后

func A(a ...int) (a,b,c int){

}

当给函数传入一个切片,在函数内部修改切片中的值会影响到函数外部;
当给函数直接传入值时,在函数内部修改值不会影响外部,而当给函数传入地址时,在函数内部修改则会影响外部

// 切片为引用地址,故会改变值
func main(){
    s1 := []int{1,2}
    A(s1)
    fmt.Println(s1)
}
func A(s [] int){
    s[0] = 5
    s[1] = 6
    fmt.Println(s)
}

// 外部a不会改变
func main(){
    a :=1
    A(a)
    fmt.Println(a)
}
func A(a int){
    a = 5
    fmt.Println(a)
}

// 由于传入的是指针型变量,外部a会改变
func main(){
    a :=1
    A(&a)
    fmt.Println(a)
}
func A(a *int){
    *a = 5
    fmt.Println(*a)
}

1.2匿名函数

将函数类型赋值给一个变量,如下将一个函数赋值给a

func main(){
    a :=func() {
        fmt.Println("Function")
    }
    a()
}

func closure(x int) func(int) int {
    return func(y int) int{
        return x+y
    }
}

1.3闭包

闭包定义:定义在一个函数内部的函数,静态保存所有了父级作用域的内部函数。
闭包作用:1.将函数作为参数传入另外一个函数;2.实现封装,管理私有变量和私有方法,将变量(状态)的变化封装在安全的环境中。3.这些变量的值始终保持在内存中,不会发生改变。
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包。

1.3.1python中的闭包

闭包就是外部函数传入使用的环境(即配置环境,下面中的a和b),内部函数使用外部函数传入的环境进行计算;传入的环境可以多次使用

def func(a, b):
    def line(x):
        return a * x - b
    return line

line = func(2, 3)
# 输出7
print(line(5))

1.3.2go中的闭包

以闭包closure为例,传入一个环境x,类型为int,返回一个函数类型,函数类型需要传入一个int类型的参数,并且换回一个int型的值,使用时f := closure(10),相当于初始化闭包,f(1)利用闭包进行计算
闭包中环境的地址始终一样,如下面x中的地址不会发生改变。

func main(){
 f := closure(10)
 fmt.Println(f(1))
}

func closure(x int) func(int) int {
    return func(y int) int {
        return x+y
    }
}

2defer

1.defer的执行方式类似其他语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行;
2.即使函数发生严重错误也会执行;
3.支持匿名函数的调用;
4.常用于资源清理、文件关闭、解锁以及记录时间等操作;
5.通过与匿名函数配合可在return之后修改函数计算结果;
6.如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址;
7.go中没有异常机制,但有panic/recover模式来处理错误;
8.panic可以在任何地方引发,但recover只有在defer调用的函数中有效。

func B(){
// 打印顺序a,c,b
    fmt.Println("a")
    defer fmt.Println("b")
    defer fmt.Println("c")
}

因为输入的值,故输入的是0,1,2

func B(){
// 打印顺序a,2,1,0
    for i:=0;i<3;i++{
        defer fmt.Println(i)
    }
    fmt.Println("a")
}

defer中使用匿名函数,匿名函数后大括号后必须接()表示调用,如下。
理解:如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址;
如下B函数因为没有传递参数,所以传入的是变量i的地址,因为最后i=3不满足条件退出,所以i为3,最后都打印3。
C函数因为传入了参数i,所以获得了拷贝,最后输出2,1,0

func B(){
// 打印顺序a,3,3,3
for i:=0;i<3;i++{
    defer func(){
            fmt.Println(i)
    }()
}
    fmt.Println("a")
}

func C(){
    // 打印顺序a,2,1,0
    for i:=0;i<3;i++{
        defer func(i int){
            fmt.Println(i)
        }(i)
    }
    fmt.Println("a")
}

3panic及recover的使用

defer需要在panic之前使用;panic相当于python中的抛出错误raise用法;抛出错误后,panic之后的代码不会被执行,但之前的defer仍然会被执行;
recover恢复运行,相当于捕获异常,必须放在defer中使用,相当于python中的exception
简单来讲:go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理

func C()  {
    fmt.Println("func A")
}

func CC()  {
    defer func() {
        if err:=recover();err!=nil{
            fmt.Println("Recover in CC")
        }
    }()
    panic("panic in CC")
}

func CCC()  {
    fmt.Println("panic in CCC")
}

    C()
    CC()
    CCC()

4练习

在for循环下定义函数,凡是不传递参数的,最后使用的都是一个地址,故使用的都是打破循环那个值,例子如下。

func F(){
    var fs = [4] func(){}
    for i:=0;i<4;i++{
        defer fmt.Println("defer i=", i)
        defer func() {fmt.Println("defer_closure i=", i)}()
        fs[i] = func() {fmt.Println("closure i=", i)}
    }
    for _,f:= range fs {
        f()
    }
}

输出结果:
closure i= 4
closure i= 4
closure i= 4
closure i= 4
defer_closure i= 4
defer i= 3
defer_closure i= 4
defer i= 2
defer_closure i= 4
defer i= 1
defer_closure i= 4
defer i= 0

相关文章

  • 第四节函数

    1.1函数 1.go函数不支持嵌套、重载和默认参数;2.但支持以下特性:无需声明原型、不定长度变参、多返回值、命名...

  • 第四节: Dart 函数使用,声明函数/匿名函数/可选参数/作用

    Dart 语法学习目录 第一节: Dart 语法了解,认识变量,常量,数据类型[https://www.jians...

  • function()编写函数

    之前在R语言入门--第四节(数据管理进阶)笔记的最后部分以两个例子简单学习了利用function()自定义编写函数...

  • 2022-06-20

    今日上午第二节借助追梦之旅专练实际问题与函数图象 第四节三楼会议室接受中招监考培训

  • 2021-01-18

    上午第四节处理《面对面》中附带的二次函数专题卷 已是强弩末,劲儿亦小多。 不敢松口气,继续把卷做。

  • 2018-12-05:《有无之境》

    第四节

  • 2022-09-16教学一日

    计划: 上午第四节—— 重点两道题目,分清楚类型。 一个转化为最值问题,一题多解是渗透三角函数辅助,使用圆的参数方...

  • (12)班的数学课(6)-2022-11-22

    让课堂充满欢笑。 今天的教学内容是一次函数的应用,难度渐增,依然分成两节课进行教学,上午第四节完成课本例题教学,下...

  • 墨的第四节

  • 只要你钓鱼,这些问题你肯定会遇到,超实用!

    一、鱼杆卡住的解决方法 方法1:第一、二节卡住,那么先拆开。取第一二节和第四节,把一二节套在第四节里,左手把第四节...

网友评论

      本文标题:第四节函数

      本文链接:https://www.haomeiwen.com/subject/wyktoctx.html