11、函数基础

01、函数定义 -- 有返回值

--golang是强类型的语言,因此传参和返回时都需要定义参数类型·
    --定义示例:
        func 函数名(参数)(返回值){
            函数体
        }

    --代码示例如下:
        func sum(x int, y int)(ret int){  // 返回值有返回名 和 返回类型
            return x+y
        }

        func intSum(x int, y int) int {  // 返回仅类型也可 [会有两个空格在返回值类型两边]
	        return x + y
        }

        func main(){
            r := sum(1, 2)
            fmt.Println(r)
        }

02、函数定义 -- 无返回值

--代码示例如下:
    func sum(x int, y int){  // 无返回值时,只需要一个小括号即可,不需要定义返回值
        fmt.Println(x + y)
    }

03、函数定义 -- 无参数 无返回值

--代码示例如下:
    func sum(){  // 无返回值,无参数就没有必要定义参数和返回值
        fmt.Println(1+2)
    }

04、函数定义 -- 无参数  有返回值

--代码示例如下:
    func sum() int {  // 有返回值,就必须有对应的返回类型
        return 1 + 2
    }

05、函数返回值 -- 定义了返回值 和 返回类型,其实只写一个return 也是可以的,前提是代码中使用了定义的返回值

--代码示例如下:
    func sum(x int, y int)(ret int){
        ret = x + y  // 这里 ret 相当于已经定义直接使用即可不要定义赋值
        return  // 使用 return ret 也可以
    }

06、函数多个返回值

--代码示例如下:
    func sum()(int, string){
        return 1, "liming"
    }

    func main(){
        _, n := sum()
        fmt.Printin(n)
    }

07、函数参数类型简写

--代码示例如下:
    // 参数类型一致时简写:
    // 当参数中连续多个参数类型一致时,我们可以将非最后一个参数的类型省略
    func sum(x, y, z int, m, n string, i, j bool){
        fmt.Pringln("hello a")
    }

08、可变长参数:必须放在参数列表最后,且可变长参数列表在函数中是切片类型

--代码示例如下:
    package main

    // 元素类型为map的字典,即列表中含字典
    import (
	    "fmt"
    )

    // 定义一个加法函数
    func multiprint(x string, y ...int) {
	    fmt.Println(x) // liming
	    fmt.Println(y) // [1 2 3 4 5]
	    fmt.Printf("%T\n", y) // []int
    }

    func f7(x string, y ...int) {
	    fmt.Println(x) // liming
	    fmt.Println(y) // [1 2 3 4]
    }

    func main() {
	    multiprint("liming", 1, 2, 3, 4, 5)
	    f7("liming", 1, 2, 3, 4)
    }

09、defer的定义和使用

--在golang中函数中不能嵌套函数 和 python不同

--defer定义:defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

--defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。这里将涉及到最基本的下面三个应用了:
    1. 关闭文件句柄
    2. 锁资源释放
    3. 数据库连接释放

--这里defer类似于python中的__enter__ 和 __exit__上下文管理机制,但更加丰富。

--代码示例01:所以defer可以用来对需要处理,但容易忘记的操作提前定义好,避免出现漏操作
    // 一般用在 文件资源释放 数据库连接 socket编程时
    // 下面几个都是示例,自己没试编写一下练练手
    func deferdemo() {
	    fmt.Println("start")
	    defer fmt.Println("嘿嘿嘿")
	    defer fmt.Println("哈哈哈")
	    fmt.Println("end")
    }

    --输出结果如下:
        start
        哈哈哈
        嘿嘿嘿
        heiheihei
--golang中函数的return操作不是原子操作,分为两步:
    --01、返回值赋值
    --02、将返回值真正传递出去

--defer执行时间,恰好在两者之间:
    --01、返回值赋值
    --02、执行defer函数
    --03、将返回值真正传递出去

--代码示例01:
    // 下面几个都是示例,自己没试编写一下练练手
    func f1() {
	    // 01、这里的核心就是defer执行顺序,先将x结果赋值给返回值,即返回5
	    // 02、再对x进行+1操作,此时x变成6.但是已经不影响返回值了
	    // 03、将返回值真正返回
	    x := 5
	    defer func() {
		    x++  // 向外找,找到了x但是指向的表示return的那个x,所以也就没有指到返回值内存空间,因此无法修改。
	    }()
	    return x
    }

    func main() {
	    fmt.Println(f1)
    }

--代码示例01打印结果:
    -- 5

--代码示例结果02:
    // 下面几个都是示例,自己没试编写一下练练手
    func f2() (x int) {
	    // f1中,go返回值x和函数体中x其实不一样,分属于两片不同内存
	    // 函数体中x是局部的,返回值中x是要给全局的。所以不一样
	    // 函数定义时的返回()其实和return中返回的是同一片内存,属于外部的、全局的。所以f2就可以修改
	    defer func() {
		    x++ // 这里的x向外找找到了,x int 这是一个返回值的内存空间,对其操作影响了返回值
	    }()
	    return 5
    }

    func main() {
	    fmt.Println(f2())
    }

--代码示例02打印结果:
    -- 6

--代码示例结果03:
    // 下面几个都是示例,自己没试编写一下练练手
    func f3() (y int) {
    	x := 5
	    defer func() {
		    x++  // 由于没有传参,向外找找到了x,因此修改的是x。此时x已经被赋值了所以无法更改
	    }()
	    return x  // 返回值 y=x=5
    }

    func main() {
	    fmt.Println(f3())
    }

--代码示例03打印结果:
    -- 5

--代码示例结果04:
    func f4() (x int) {
	    defer func(x int) {
		    x++
	    }(x)
	    return 5
    }

--代码示例04打印结果:
    -- 5

10、作用域

--全局变量:定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。

--代码示例如下:
    var num int = 100

    func f1() {
        // 函数中查找变量顺序:
        //    01、先在函数内部查找
        //    02、找不到就到函数外层查找,知道找到全局变量。
        num := 15
	    fmt.Printf("%d\n", num)
    }

    func main() {
	    f1()
    }    
--局部变量:只在某一个代码块中生效
    01、 函数内定义的变量无法在该函数外使用:
        func f1() {
	        //定义一个函数局部变量x,仅在该函数内生效
	        var num int64 = 102
	        fmt.Printf("x=%d\n", num)
        }

        func main() {
	        f1()  
	        fmt.Println(num) // 此时无法使用变量x,会报错
        }

    02、如果局部变量和全局变量重名,优先访问局部变量。
        var num int = 100

        func f1() {
        	num := 15
	        fmt.Printf("%d\n", num)  // 优先打印num = 15
        }

        func main() {
	        f1()
        }
--golang中有三种作用域:语句块作用域  函数作用域  全局作用域

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值