函数

2020-03-09  本文已影响0人  isuntong

函数初识

package main

import "fmt"

//24
func main() { //程序的主函数,是一个特殊的函数
    /*
    函数:function
    一、概念:
        具有特定功能的代码,可以被多次调用执行
    二、意义:
        1. 可以避免重复的代码
        2. 增强程序的扩展性
    三、使用:
        1. 函数定义声明
        2. 函数使用
    四、语法:
        func funcName(parametername type1,parametername
            type2) (output1 type1,output2 type2) {
            //逻辑代码
            //返回多个值
            return value1,value2
        }
        参数列表:形参用于接收外部传入函数中的数据
        返回值列表:函数执行后返回给调用处的结果
    五、调用
        函数名(实际参数)
    六、注意事项
        函数必须先定义再调用
        函数名不能冲突
    */
    getSum()

}

//定义一个函数
func getSum(){
    sum := 0
    for i:=1;i<=10;i++ {
        sum += i
    }
    fmt.Printf("1-10的和为:%d\n", sum)
}

函数的参数

/*
函数的参数
*/
//定义一个函数
func getSum(n int){
    sum := 0
    for i:=1;i<=n;i++ {
        sum += i
    }
    fmt.Printf("1-%d的和为:%d\n", n, sum)
}

函数的多个参数

/*
多个参数 实参形参一一对应,调用的时候顺序、个数、类型都必须一一对应
*/
func getAdd(a int, b int) {  // (a,b int)
    sum := a + b
    fmt.Printf("%d + %d = %d\n",a,b,sum)
}

可变参数

/*
可变参数 个数不确定,类型确定

语法:
    参数名 ... 参数的类型
    对于函数,可变参数相当于一个切片
    调用函数,可以传 0-多个 参数

注意事项:
    如果一个函数的参数是可变参数,同时还有其他的参数,可变参数要放在参数列表的最后
    一个函数的参数列表中最多只能有一个可变参数

*/
func getSums(nums ... int) {
    // fmt.Printf("%T\n",nums) //[]int
    sum := 0
    for i:=0;i<len(nums);i++ {
        sum += nums[i]
    }
    fmt.Println("总和是:",sum)
}

参数传递

/*
参数传递

值传递:传递的参数的副本
    值类型的数据、默认是值传递,基础类型,array,struct

引用传递
    引用类型 slice,map、chan
*/

函数的返回值

/*
函数的返回值
    一个函数执行后,返回给函数的调用处的执行结果就叫返回值

*/

func getSum1()(int) {
    sum := 0
    for i:=0;i<=10;i++ {
        sum += i
    }
    return sum
}

func getSum2()int {
    sum := 0
    for i:=0;i<=10;i++ {
        sum += i
    }
    return sum
}

//指定返回数据
func getSum3()(a int) {
    sum := 0  //不用再定义了
    for i:=0;i<=10;i++ {
        sum += i
    }
    // return 谁就是把谁赋值给返回给 a
    return sum
}

函数的多返回值

/*
多返回值
    函数的返回结果,必须和函数定义的一致:类型,个数,顺序

注意:
    1. 将函数的结果返回给调用处
    2. 同时结束了该函数的执行

空白标识符,准们用来舍弃数据: _
*/
//求周长和面积
func rectangle(len,wid float64)(float64,float64) {
    perimeter := (len + wid)*2
    area := len * wid
    return perimeter,area
}

func rectangle2(len,wid float64)(peri float64,area float64) {
    peri = (len + wid)/2
    area = len * wid
    return
}

res1,res2 := rectangle(5,3)
    fmt.Println("周长:",res1,",面积:",res2)

return语句

package main

//25
func main() {

}

/*
return语句
    1. 将函数的结果返回给调用处
    2. 同时结束了该函数的执行

注意事项:
    1. 一个函数定义了返回值,return数据和函数定义的一致:个数、类型、顺序
    2. 可以使用_,来舍弃多余的返回值
    3. 如果定义了有返回值,保证一定要有return语句执行
    4. 没有定义返回值,也可以用return语句结束掉函数
*/

函数中变量的作用域

package main

import "fmt"

var num = 1000

//25
func main() {
    fmt.Println(num)
    num := 1
    fmt.Println(num)
    if num:=10;num==10 {
        fmt.Println(num)
    }
}

/*
return语句
    1. 将函数的结果返回给调用处
    2. 同时结束了该函数的执行

注意事项:
    1. 一个函数定义了返回值,return数据和函数定义的一致:个数、类型、顺序
    2. 可以使用_,来舍弃多余的返回值
    3. 如果定义了有返回值,保证一定要有return语句执行
    4. 没有定义返回值,也可以用return语句结束掉函数
*/


/*
函数中变量的作用域
    局部变量:函数内部定义的变量

    全局变量:函数外部定义的变量

就近原则,可以里外都定义
*/

递归函数

/*
递归函数


*/

//求1-5的和
func getSumDiGui(n int)(sum int) {
    if n<=0 {
        return 0
    }
    sum = n + getSumDiGui(n-1)
    return
}

//斐波那契数列
func getFibonacci(n int)int {
    if n==1 || n==2 {
        return 1
    }
    return getFibonacci(n-1) + getFibonacci(n-2)
}

a := getSumDiGui(5)
    fmt.Println(a)
    fmt.Println(getFibonacci(12))

defer语句

多个defer:

注意点:

/*
1. defer语句
    一个函数方法执行被延迟了,主函数所有代码结束再执行

2. 用法:
    对象.close(),临时文件的删除
        文件.close()
        defer close()

    go语言中关于异常的处理,使用panic()和recover()
        panic函数用于引发恐慌,导致程序中断执行
        recover函数用于恢复程序的执行,recover()语法上要求必须在defer中执行

3.多个defer
    堆栈推迟,后进先出

4.defer函数传递参数时机:
    调用时已经传递参数,只不过代码先不执行

5.注意点
*/
func fun1(s string) {
    fmt.Println(s)
}

defer fun1("hello")
    fmt.Println("-----")
    defer fun1("world") //此时主函数为外围函数
    fmt.Println("*****")

函数的数据类型

package main

import "fmt"

//26
func main() {
    /*
    函数的类型:func()
    */
    fmt.Printf("%T\n",fun11) //func()
    fmt.Printf("%T\n",fun12) //func(int) int
    fmt.Printf("%T\n",fun13) //func(float64, int, int) (int, int)
}

func fun11() {

}

func fun12(a int)int {
    return 0
}

func fun13(a float64,b,c int)(int,int) {
    return 0,0
}

函数的本质

fmt.Println(fun11)
    c := fun11
    c() //可以当作函数执行

匿名函数

/*
    匿名函数:没有名字的函数

    定义一个匿名函数,加上小括号直接调用,通常只能调用一次
    也可以使用匿名函数赋值给某个函数变量,就可以调用多次了

    Go语言支持函数式编程
        1. 将匿名函数作为另一个函数的参数,回调参数
        2. 将匿名函数作为另一个函数的返回值,可以形成闭包结构
    */
    func () {
        fmt.Println("匿名函数")
    }()

    fun3 := func () {
        fmt.Println("我也是匿名函数")
    }
    fun3()
    fun3()

    //定义带参数的匿名函数
    func (a,b int) {
        fmt.Println(a,b)
    }(1,2)

    //定义带返回值的匿名函数
    res1 := func (a,b int) int {
        return a+b
    }(1,2)
    fmt.Println(res1)

    //不直接调用,赋值给函数变量
    res2 := func (a,b int) int {
        return a+b
    }
    res2(1,2)

回调函数

package main

import "fmt"

//27
func main() {
    /*
    高阶参数:
        使用go语言的数据类型的特点,可以将一个函数作为另一个函数的参数

    fun1(),fun2()
    将fun1函数作为fun2函数的参数

        fun2函数:就叫高阶函数
            接收了一个函数作为参数的函数,高阶函数
        fun1函数:回调函数
            作为了一个函数的参数的函数,叫回调函数
    */

    fmt.Printf("%T\n",add)  //func(int, int) int
    fmt.Printf("%T\n",oper) //func(int, int, func(int, int) int) int

    res1 := add(1,2)
    fmt.Println(res1)

    res2 := oper(10,20,add)
    fmt.Println(res2) //10 20 0x4a0bf0

    //用匿名函数
    funadd := func(a,b int)int{
        return a+b
    }

    res4 := oper(10,20,funadd)
    fmt.Println(res4)

    res5 := oper(100,200, func(a,b int) int {
        return a+b
    })
    fmt.Println(res5)

}

//设计函数,两个数的加减运算
//加法
func add(a,b int) int {
    return a+b
}

//add函数传进 oper 不会马上执行,所以叫回调函数

func oper(a,b int, fun func(int,int)int) int {
    fmt.Println(a,b,fun)
    res := fun(a,b)
    return res
}


闭包

package main

import "fmt"

//28
func main() {
    /*
    go语言支持函数式编程
        支持函数作为另一个函数的参数
        也支持函数作为另一个函数的返回值
    */
    res1 := increment()
    fmt.Printf("%T\n",res1) //func() int
    fmt.Println(res1) //0x4a0d40
    v1 := res1()
    fmt.Println(v1) //1
    v2 := res1()
    fmt.Println(v2) //2

    res2 := increment()
    fmt.Println(res2) //0x4a0d40  重新创建了变量i,内存改变
    v3 := res2()
    fmt.Println(v3) //1
}
/*
一个外层函数中,有内层函数,内层函数会操作外层函数局部变量,并且该外层函数的返回值就是
这个内层函数,这个内层函数和外层函数的局部变量,统称为闭包结构

局部变量生命周期发生改变,正常的局部变量随着函数调用而创建,随着函数的结束而销毁
但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还要继续使用
*/

func increment()func()int {
    //定义一个局部变量
    i := 0 //这个i生命周期发生改变
    //定义一个匿名函数,给变量自增并返回
    fun := func ()int{
        i++
        return i
    }
    //返回匿名函数
    return fun
}
上一篇下一篇

猜你喜欢

热点阅读