009. golang 函数 function

函数function

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

package main

import (
    "fmt"
)

func main() {
    fmt.Println(A(1, "a"))

    fmt.Println(B(2, "b"))

    a, b, c := 1, 2, 3
    C("y", a, b, c)
    fmt.Println(a, b, c)

    arr := []int{1, 2, 3, 4, 5, 6}
    D(arr)
    fmt.Println(arr)

    e := 2
    E(&e)
    fmt.Println(e)

}

func A(a int, b string) (int, string) {
    return a, b
}

func B(a int, b string) (A int, B string) {
    A, B = a, b
    return
}

//不定长变参,只能作为最后一个参数 而且拷贝的都是值拷贝
func C(x string, a ...int) {
    a[0] = 4
    a[1] = 5
    a[2] = 6
    fmt.Println(x, a)
}

//数组的话都是地址拷贝
func D(a []int) {
    a[0] = 10
    a[1] = 11
    a[2] = 12
    fmt.Println(a)
}

//如果 值拷贝 想更改为 地址拷贝
//传参数的时候加上 &
//方法形参加上 *
func E(e *int) {
    *e = 9
    fmt.Println(*e)
}

package main

import (
    "fmt"
)

func main() {
    //匿名函数
    a := func() {
        fmt.Println("Func A")
    }
    a()

    fmt.Println()

    //匿名函数+闭包
    f := test(10)
    fmt.Println("------------------------")
    fmt.Println(f(1))
    fmt.Println(f(2))

}

func test(x int) func(int) int {
    fmt.Printf("%p,%d\n", &x, x)
    return func(y int) int {
        fmt.Printf("%p,%d\n", &x, x)
        return x + y
    }
}

defer

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

package main

import (
    "fmt"
)

func main() {
    fmt.Println("a")
    defer fmt.Println("b")
    defer fmt.Println("c")

    fmt.Println("------------------")

    for i := 0; i < 3; i++ {
        defer func() {
            fmt.Println(i)
        }()
    }
    fmt.Println("---------------")
}

package main

import (
    "fmt"
)

func main() {
    A()
    B()
    C()
}

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

func B() {
    panic("panic in B")
}

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

package main

import (
    "fmt"
)

func main() {
    A()
    B()
    C()
}

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

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

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

package main  

import (  
    "fmt"  
)  

func main() {  
    var fs = [4]func(){} //声明一个function类型的slice,长度为4  

    for i := 0; i < 4; i++ {  
        defer fmt.Println("defer i= ", i)                       //这是一个i作为参数传进去的输出,因为i是int型,所以遵循一个规则值拷贝的传递,还有defer是倒序执行的,所以先后输出3,2,1,0,跟下面的defer交替执行4次  
        defer func() { fmt.Println("defer_closure i = ", i) }() //执行完下面的代码后,到了该defer了,这也是一个匿名函数,同样的也没有参数,也没有定义i,所以这也是个闭包,用的也是外面的i,所以先输出4,接着执行上面的defer,这样反复执行4次  
        fs[i] = func() { fmt.Println("closure i = ", i) }       //把相应的4个匿名函数存到function类型的slice里,因为这是个匿名函数,又没有参数,且也没有定义i,所以i就是外层函数的地址引用,就是for循环的i的地址,执行完for后i的值为4,所以输出4个4  
    }  

    for _, f := range fs { //用for循环对slice的调用,f为slice的值,即匿名函数,而f()则是对匿名函数的调用  
        f()  
    }  
}  

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏禅林阆苑

golang之fmt格式占位符总结 【原创】

golang之fmt格式占位符总结 Write By CS逍遥剑仙 我的主页: www.csxiaoyao.com GitHub: githu...

6198
来自专栏前端技术总结

jQuery中parents()、parent()和closest()的区别

本方法用于选择给定jQuery对象中包含的DOM元素或者DOM元素集的祖先节点,并将这些节点包装成jQuery对象返回,返回的节点集是以从里到外的顺序排序的。

1.7K109
来自专栏Python小屋

详解Python切片技术

切片也是Python序列的重要操作之一,除了适用于列表之外,还适用于元组、字符串、range对象,但列表的切片操作具有最强大的功能。不仅可以使用切片来截取列表中...

3074
来自专栏GreenLeaves

JavaScript之怎样获取元素节点

JavaScript获取元素节点一共有三种方法,分别是通过元素ID、通过标签名字和通过类名字来获取; 1.通过元素ID属性的ID值来获得元素对象-getElem...

1818
来自专栏张善友的专栏

c#处理空白字符

空白字符是指在屏幕不会显示出来的字符(如空格,制表符tab,回车换行等)。空格、制表符、换行符、回车、换页垂直制表符和换行符称为 “空白字符”,因为它们为与间距...

2286
来自专栏Golang语言社区

Go语言中字符串的查找方法小结

1.func Contains(s, substr string) bool这个函数是查找某个字符是否在这个字符串中存在,存在返回true import ( ...

35610
来自专栏Golang语言社区

【基础篇】Go 语言范围(Range)

Go 语言范围(Range) Go 语言中 range 关键字用于for循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)...

37716
来自专栏深度学习思考者

C++常见问题(三)——宏定义、const、static、sizeof的相关实例

第一部分 宏定义   宏定义的语法格式:#define <标识符><字符串>,其中的标识符就是所谓的符号常量,也称为”宏名”。预处理工作也叫宏展开。宏定义不占用...

19510
来自专栏积累沉淀

Linux shell ${}简单用法

Linux shell ${}简单用法 [转]http://linux.chinaunix.net/techdoc/develop/2007/05/05/9...

1966
来自专栏Golang语言社区

厚土Go学习笔记 | 21. range用法

range是一个内置函数。可以遍历数组、切片slice、字典map。 当遍历数组和切片的时候,返回的是索引和元素。 当遍历字典的时候,返回字典的键和值。 //r...

42610

扫码关注云+社区

领取腾讯云代金券