go【第三篇】函数

函数定义和使用

go的函数也是一等对象

Go语言中,函数的基本组成为:关键字func、函数名、参数列表、返回值、函数体和返回语句 

package main // 规范:包名和入口函数必须是main

import (
    "fmt"
)

//无参数无返回值
func Add() {
    fmt.Println(666)
}

//无参数有返回值
func Add2() (a int){
    return 999
}

//有参数无返回值
func Add3(a int, b int) {
    fmt.Println(a, b)
}


//有参数有返回值
func Add4(a int, b int) (sum int) {
    return a + b // 支持多重返回值
}

/*return 另一种写法
func Add4(a int, b int) (sum int) {
    sum = a + b
    return  // 支持多重返回值
}
*/

//多个返回值
//写法一
//func Add5(a int, b int) (c,d  int) {
//    return a, b // 支持多重返回值
//}

//写法二(官方推荐写法)
func Add5(a int, b int) (c int,d  int) {
    return a, b // 支持多重返回值
}

//写法三
//func Add5(a int, b int) (int, int) {
//    return a, b // 支持多重返回值
//}

func main() {
    Add()  //无参数无返回值
    fmt.Println(Add2())  //无参数有返回值
    Add3(1, 2)

    sum := Add4(1, 2)
    fmt.Println(sum)

    fmt.Println(Add5(1, 2))
}

/*输出
2
2
*/

变量作用域

函数外的每个语句都必须以关键字开始(varfunc 等等),因此 := 结构不能在函数外使用。

没有明确初始值的变量声明会被赋予默认值(0 false "" nil等)

局部变量

package main //必须

import "fmt"

func test() {
    a := 10
    fmt.Println("a = ", a)
}

func main() {
    //定义在{}里面的变量就是局部变量,只能在{}里面有效
    //执行到定义变量那句话,才开始分配空间,离开作用域自动释放
    //作用域,变量其作用的范围

    //a = 111
    {
        i := 10
        fmt.Println("i = ", i)
    }
    //i = 111

    if flag := 3; flag == 3 {  //flag不在{}内丹属于if块,依然是局部变量
        fmt.Println("flag = ", flag)
    }

    flag = 4

}

全局变量

package main //必须

import "fmt"

func test() {
    fmt.Println("test a = ", a)
}

//定义在函数外部的变量是全局变量
//全局变量在任何地方都能使用
var a int

func main() {
    a = 10
    fmt.Println("a = ", a)

    test()
}

变量重名

package main //必须

import "fmt"

var a byte //全局变量

func main() {
    var a int //局部变量

    //1、不同作用域,允许定义同名变量
    //2、使用变量的原则,就近原则
    fmt.Printf("%T\n", a) //int

    {
        var a float32
        fmt.Printf("2: %T\n", a) //float32
    }

    test()

}

func test() {
    fmt.Printf("3: %T\n", a) //uint8, 就是byte
}

函数参数

Go没有默认参数和位置参数

不定参数

类似python的冗余参数

不定参数是指函数传入的参数个数为不定数量 ,...type必须是最后一个参数,args把参数封装成数组

同一类型的不定参数

package main

import "fmt"

func main() {
    myfunc(1,2)
}

func myfunc(args ...int) {
    fmt.Println(args)
    for _, arg := range args {
    fmt.Println(arg)
    }
}
#######
[1 2]

任意类型的不定参数

package main
import "fmt"
func MyPrintf(args ...interface{}) {
    fmt.Println(args)
    for _, arg := range args {
        switch arg.(type) {
            case int:
            fmt.Println(arg, "is an int value.")
            case string:
            fmt.Println(arg, "is a string value.")
            case int64:
            fmt.Println(arg, "is an int64 value.")
            default:
            fmt.Println(arg, "is an unknown type.")
        }
    }
}

func main() {
    var v1 int = 1
    var v2 int64 = 234
    var v3 string = "hello"
    var v4 float32 = 1.234
    MyPrintf(v1, v2, v3, v4)
}
#################
[1 234 hello 1.234]
is an int value.
is an int64 value.
hello is a string value.
1.234 is an unknown type.

内建函数

函数类型

package main //必须

import "fmt"

func Add(a, b int) int {
    return a + b
}

func Minus(a, b int) int {
    return a - b
}

//函数也是一种数据类型, 通过type给一个函数类型起名
//FuncType它是一个函数类型
type FuncType func(int, int) int //没有函数名字,没有{}

func main() {
    var result int
    result = Add(1, 1) //传统调用方式
    fmt.Println("result = ", result)

    //声明一个函数类型的变量,变量名叫fTest
    var fTest FuncType
    fTest = Add            //是变量就可以赋值
    result = fTest(10, 20) //等价于Add(10, 20)
    fmt.Println("result2 = ", result)

    fTest = Minus
    result = fTest(10, 5) //等价于Minus(10, 5)
    fmt.Println("result3 = ", result)
}

/*输出
result =  2
result2 =  30
result3 =  5
*/
package main //必须

import "fmt"

type FuncType func(int, int) int

//实现加法
func Add(a, b int) int {
    return a + b
}

func Minus(a, b int) int {
    return a - b
}

func Mul(a, b int) int {
    return a * b
}

//回调函数,函数有一个参数是函数类型,这个函数就是回调函数
//计算器,可以进行四则运算
//多态,多种形态,调用同一个接口,不同的表现,可以实现不同表现,加减乘除
//现有想法,后面再实现功能
func Calc(a, b int, fTest FuncType) (result int) {
    fmt.Println("Calc")
    result = fTest(a, b) //这个函数还没有实现
    //result = Add(a, b) //Add()必须先定义后,才能调用
    return
}

func main() {
    a := Calc(1, 1, Mul)
    fmt.Println("a = ", a)
}

/*
Calc
a =  1
*/
回调函数

匿名函数

package main //必须

import "fmt"

func main() {
    a := 10
    str := "mike"

    //匿名函数,没有函数名字, 函数定义,还没有调用
    f1 := func() { //:= 自动推导类型
        fmt.Println("a = ", a)
        fmt.Println("str = ", str)
    }

    f1()

    //给一个函数类型起别名
    type FuncType func() //函数没有参数,没有返回值
    //声明变量
    var f2 FuncType
    f2 = f1
    f2()

    //定义匿名函数,同时调用
    func() {
        fmt.Printf("a = %d, str = %s\n", a, str)
    }() //后面的()代表调用此匿名函数

    //带参数的匿名函数
    f3 := func(i, j int) {
        fmt.Printf("i = %d, j = %d\n", i, j)
    }
    f3(1, 2)

    //定义匿名函数,同时调用
    func(i, j int) {
        fmt.Printf("i = %d, j = %d\n", i, j)
    }(10, 20)

    //匿名函数,有参有返回值
    x, y := func(i, j int) (max, min int) {
        if i > j {
            max = i
            min = j
        } else {
            max = j
            min = i
        }

        return
    }(10, 20)

    fmt.Printf("x = %d, y = %d\n", x, y)

}

闭包

情况一

package main //必须

import "fmt"

func main() {
    a := 10
    str := "mike"

    func() {
        //闭包以引用方式捕获外部变量
        a = 666
        str = "go"
        fmt.Printf("内部:a = %d, str = %s\n", a, str)
    }() //()代表直接调用

    fmt.Printf("外部:a = %d, str = %s\n", a, str)

}

情况二

package main //必须

import "fmt"

//函数的返回值是一个匿名函数,返回一个函数类型
func test02() func() int {
    var x int //没有初始化,值为0

    return func() int {
        x++
        return x * x
    }
}

func main() {

    //返回值为一个匿名函数,返回一个函数类型,通过f来调用返回的匿名函数,f来调用闭包函数
    //它不关心这些捕获了的变量和常量是否已经超出了作用域
    //所以只有闭包还在使用它,这些变量就还会存在。
    f := test02()
    fmt.Println(f()) //1
    fmt.Println(f()) //4
    fmt.Println(f()) //9
    fmt.Println(f()) //16
    fmt.Println(f()) //25


defer

defer语句在函数结束时执行

如果代码哪部分有异常,defer代码依然执行

 

package main //必须

import "fmt"

func main() {
    //defer延迟调用,main函数结束前调用
    defer fmt.Println("bbbbbbbbbbbbb")

    fmt.Println("aaaaaaaaaaaaaaa")
}
/*
aaaaaaaaaaaaaaa
bbbbbbbbbbbbb
*/

多个defer

package main //必须

import "fmt"

func test(x int) {
    result := 100 / x

    fmt.Println("result = ", result)
}

func main() {

    defer fmt.Println("aaaaaaaaaaaaaa")

    defer fmt.Println("bbbbbbbbbbbbbb")

    //调用一个函数,导致内存出问题
    defer test(0)

    defer fmt.Println("ccccccccccccccc")
}

/*
ccccccccccccccc
bbbbbbbbbbbbbb
aaaaaaaaaaaaaa
*/

  

package main //必须

import "fmt"

func test(x int) {
    result := 100 / x

    fmt.Println("result = ", result)
}

func main() {

    defer fmt.Println("aaaaaaaaaaaaaa")

    defer fmt.Println("bbbbbbbbbbbbbb")

    //调用一个函数,导致内存出问题
    test(0)

    defer fmt.Println("ccccccccccccccc")
}

/*
bbbbbbbbbbbbbb
aaaaaaaaaaaaaa
*/

 

  

  




posted @ 2018-02-08 12:16  沐风先生  阅读(195)  评论(0编辑  收藏  举报