美文网首页
Go语言基础02——函数、工程管理

Go语言基础02——函数、工程管理

作者: Spring618 | 来源:发表于2019-03-15 17:19 被阅读0次

    函数的基本使用

    函数构成代码执行的逻辑结构。在Go语言中,函数的基本组成为:关键字func、函数名、参数列表、返回值、函数体和返回语句。

    函数定义说明:
    l func:函数由关键字 func 开始声明
    l FuncName:函数名称,根据约定,函数名首字母小写即为private,大写即为public
    l 参数列表:函数可以有0个或多个参数,参数格式为:变量名 类型,如果有多个参数通过逗号分隔,不支持默认参数
    l 返回类型:
    ① 上面返回值声明了两个变量名o1和o2(命名返回参数),这个不是必须,可以只有类型没有变量名
    ② 如果只有一个返回值且不声明返回值变量,那么你可以省略,包括返回值的括号
    ③ 如果没有返回值,那么就直接省略最后的返回信息
    ④ 如果有返回值, 那么必须在函数的内部添加return语句

    下面通过代码讲述函数的基本使用:

    package main
    
    import "fmt"
    
    func sing() {
        fmt.Println("i am singing!")
    }
    
    func sing2(lrc string) { // 注意不能与sing()函数重名
        fmt.Println("i am singing : " + lrc)
    }
    func sing3(args ...string) { // 注意不能与sing()函数重名
    
        for _, data := range args {
            fmt.Println("i am singing : " + data)
        }
    
    }
    
    func sing4(args ...string) { // 注意不能与sing()函数重名
        sing3(args[:2]...)
    }
    func sing5(args ...string) { // 注意不能与sing()函数重名
        sing3(args[2:]...)
    }
    func myfunc01() int {
        return 666
    }
    
    func myfunc02() (result int) { // go语言推荐写法
        return 777
    }
    func myfunc03() (result int) { // go语言推荐写法
        result = 888
        return
    }
    
    func calc(a, b int) (r1, r2 int) { // go语言推荐写法
        r1 = a + b
        r2 = a * b
        return
    }
    
    func main() {
        fmt.Println("函数的基本使用演示案例")
    
        // 1. 无参数无返回值
        sing()
        // 2. 有参数无返回值:普通参数列表
        sing2("我爱go语言")
    
        // 3. 有参数无返回值:不定参数类型
        sing3("A", "B", "C")
        sing3("哈哈哈")
        sing3()
        fmt.Println("==========")
        // 4. 不定参数的传递
        sing4("x", "y", "z", "666") // x,y
        fmt.Println("==========")
        sing5("x", "y", "z", "666") // z,666
    
        // 5. 带返回值的函数:有返回值的函数,必须有明确的终止语句,否则会引发编译错误。
        res := myfunc01()
        fmt.Println("res = ", res)
        res2 := myfunc02()
        fmt.Println("res2 = ", res2)
        res3 := myfunc03()
        fmt.Println("res3 = ", res3)
    
        // 6. 函数返回多个返回值
    
        a, b := calc(4, 5)
        fmt.Printf("a+b = %d,a*b=%d", a, b)
    }
    
    

    递归函数

    package main
    
    import "fmt"
    
    func add(i int) int {
        if i == 1 {
            return 1
        } else {
            return i + add(i-1)
        }
    
    }
    
    func main() {
        fmt.Println("函数的基本使用演示案例")
        result := add(100)
        fmt.Println("1-100的和是 :", result)
    
    }
    
    

    函数类型

    在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型。

    package main
    
    import "fmt"
    
    func add(a, b int) int {
        return a + b
    }
    func sub(a, b int) int {
        return a - b
    }
    
    type FuncType func(a, b int) int //没有函数名字,没有函数实体{}
    
    func main() {
        fmt.Println("函数类型的使用演示案例")
    
        var calc FuncType
        calc = add
        r1 := calc(1, 2)
        fmt.Println("r1 :", r1)
    
        calc = sub
        r2 := calc(8, 2)
        fmt.Println("r2 :", r2)
    
    }
    
    

    回调函数

    函数参数是函数类型,这个函数就是回调函数。

    package main
    
    import "fmt"
    
    func add(a, b int) int {
        return a + b
    }
    func sub(a, b int) int {
        return a - b
    }
    
    type FuncType func(a, b int) int //没有函数名字,没有函数实体{}
    
    // 回调函数,函数有一个参数是函数类型,这个函数就是回调函数
    
    func Calc(a, b int, f FuncType) int {
        return f(a, b)
    }
    
    func main() {
        fmt.Println("回调函数的使用演示案例")
    
        m1 := add
        r1 := Calc(1, 2, m1)
        fmt.Println("r1 = ", r1)
    
        m1 = sub
        r1 = Calc(1, 2, m1)
        fmt.Println("r1 = ", r1)
    }
    
    

    匿名函数和闭包

    所谓闭包就是一个函数“捕获”了和它在同一作用域的其它常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

    在Go语言里,所有的匿名函数(Go语言规范中称之为函数字面量)都是闭包。匿名函数是指不需要定义函数名的一种函数实现方式,它并不是一个新概念,最早可以回溯到1958年的Lisp语言。

    闭包以引用方式捕获外部变量

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("匿名函数和闭包的使用演示案例")
        a := 10
        str := "abc"
    
        ///1、匿名函数,没有函数名字,没有函数定义,也没有调用
        f1 := func() {
            fmt.Printf("a = %d, str = %s\n", a, str)
        }
        f1()
    
        // 2、给函数类型起别名
        type MyFunc func()
        var v1 MyFunc
    
        v1 = f1
        v1()
    
        //3、有带参数的匿名函数
    
        f2 := func(a, b int) {
            fmt.Printf("a = %d, b = %d\n", a, b)
        }
        f2(3, 4)
    
        // 匿名函数,同时调用
        func(a, b int) {
            fmt.Printf("a = %d, b = %d\n", a, b)
        }(55, 66)
    
        //4、匿名函数,有参数有返回值:
    
        res := func(a, b int) int {
            return a + b
        }(2, 3)
        fmt.Printf("res = %d \n", res)
    
        // 5、闭包:闭包以引用方式捕获外部变量
        aa := 10
        bb := "abc"
    
        func() {
            aa = 20
            bb = "zzz"
            fmt.Printf("内部 a = %d, b = %s\n", aa, bb) //内部 a = 20, b = zzz
        }()
        fmt.Printf("外部 a = %d, b = %s\n", aa, bb) //外部 a = 20, b = zzz
    
        fmt.Println("test01 = ", test01()) //1
        fmt.Println("test01 = ", test01()) //1
    
        fmt.Println("test02 = ", test02()) //1
        fmt.Println("test02 = ", test02()) //1
        fmt.Println("test02 = ", test02()) //1
    
        f3 := test02()
        fmt.Println("test02 f3 = ", f3()) //1
        fmt.Println("test02 f3 = ", f3()) //4
        fmt.Println("test02 f3 = ", f3()) //9
    
        //函数test02返回另一个类型为 func() int 的函数。
        //对test02的一次调用会生成一个局部变量x并返回一个匿名函数。
        //每次调用时匿名函数时,该函数都会先使x的值加1,再返回x的平方。
        //第二次调用test02时,会生成第二个x变量,并返回一个新的匿名函数。新匿名函数操作的是第二个x变量。
        //通过这个例子,我们看到变量的生命周期不由它的作用域决定:test02返回后,变量x仍然隐式的存在于f中。
    }
    
    func test01() int {
        var n int
        n++
        return n * n
    }
    
    // 函数返回是一个匿名函数,
    func test02() func() int {
        var n int
    
        return func() int {
            n++
            return n * n
        }
    
    }
    
    

    defer的使用

    关键字 defer ⽤于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行。注意,defer语句只能出现在函数或方法的内部。

    defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后。

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("defer的使用演示案例")
    
        fmt.Println("aaaaaaa")
    
        defer fmt.Println("bbbbbbb")
    
        fmt.Println("ccccccc")
    
        // aaa ccc bbb
    }
    
    

    多个defer的调用顺序:

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("多个defer的调用顺序使用演示案例")
    
        defer fmt.Println("aaaaaaa")
    
        defer fmt.Println("bbbbbbb")
    
        fmt.Println("ccccccc")
    
        //  ccc bbb aaa
    }
    
    

    defer和匿名函数的结合:

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("defer和匿名函数的结合使用演示案例")
    
        // 情形一
        a := 10
        b := "abc"
        defer func() {
            fmt.Printf("内部:a = %d,b = %s\n", a, b)
        }()
    
        a = 20
        b = "zz"
    
        fmt.Printf("外部:a = %d,b = %s\n", a, b)
    }
    
    

    defer和匿名函数的结合2:

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("defer和匿名函数的结合使用演示案例")
    
        // 情形二
        a := 10
        b := "abc"
        defer func(a int, b string) {
            fmt.Printf("内部:a = %d,b = %s\n", a, b) // 内部:a = 10,b = abc
        }(a, b)
    
        a = 20
        b = "zz"
    
        fmt.Printf("外部:a = %d,b = %s\n", a, b) //外部:a = 20,b = zz
    }
    
    

    获取命令行参数

    package main
    
    import "fmt"
    import "os"
    
    func main() {
        fmt.Println("获取命令行 使用演示案例")
    
        args := os.Args
        fmt.Println("len = ", len(args))
    
        for i, data := range args {
            fmt.Println("data[%d] = %s", i, data)
        }
    }
    
    

    导入包

    . 点操作:

    package main
    
    // 方式一
    // import "fmt"
    // import "os"
    
    // 方式二
    // import (
    //  "fmt"
    //  "os"
    // )
    
    // 方式三
    
    import . "os" // 调用函数无需通过包名
    import . "fmt"
    
    func main() {
        // fmt.Println("导入包使用演示案例")// 如果使用了.操作,则不能这样引用了
        // args := os.Args
        // fmt.Println("len = ", len(args))
    
        args := Args
        Println("len = ", len(args))
    
    }
    
    

    给包起别名:

    package main
    
    import pt "fmt"
    import ooss "os"
    
    func main() {
        pt.Println("导入包使用演示案例") // 如果使用了.操作,则不能这样引用了
        args := ooss.Args
        // fmt.Println("len = ", len(args))// err,起完别名之后不能这样使用了
        pt.Println("len = ", len(args)) // err,起完别名之后不能这样使用了
    }
    
    

    忽略此包:

    import _ "fmt"
    

    其他

    过程管理、gopath、init、go install

    END.

    相关文章

      网友评论

          本文标题:Go语言基础02——函数、工程管理

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