learnGo4-函数

函数声明


    //可变参数
    func ex1(i int, j ...int) {
        for index, _ := range j {
            j[index] *= i
        }
    }

    j := []int{1, 2, 3, 4, 5, 6, 7}
    // slice 解析调用
    ex1(2, j...)
    fmt.Println(j) //[2 4 6 8 10 12 14]

    //预设返回值
    func ex2(s string) (i int) {
        i, _ = strconv.Atoi(s)
        return
    }

    //多返回值
    func ex3(s string) (int, error) {
        i, err := strconv.Atoi(s)
        return i, err
    }
  • 可变参数,多返回值,裸返回,这是 go 函数的基本特点
  • 不支持重载,在大型工程中,重载函数只会让你调用到你意料之外的函数
  • 递归栈很大,一般的语言函数递归所能提供的最大栈大概 2k,而 go 函数递归提供动态的栈大小,最大有 2g

error

go 函数中最大的特点就是 error,在 go 的内置函数中,大多数函数第二个会返回一个 error 值,代表了调用函数失败的错误信息

通常我们并不能保障我们的函数一定会被成功调用,就需要返回 error 来明确提示错误信息,通常他会被作为第二个参数返回,如果调用结果只有两种情况,通常返回一个 bool 表示调用成功或失败

go 在设计时,希望能尽可能的处理错误信息,或尽可能的给出严谨的错误,如果说 java 只做正确的情况,对于所有错误情况通过异常抛出,那么 go 则是希望除了正确情况外,尽可能去处理意料之内的错误情况

提供几个 error 处理的函数
- fmt.Errorf() //返回格式化后的错误信息
- log.Fatal() //打印错误信息,默认带上服务器时间做前缀,可以自定义前缀
- 很多错误常量有利于我们对错误的处理,比如 io.EOF 代表文件读取到尾部了,读取不到了

函数变量

在 go 中,函数是一等公民,它也有类型,也可以作为变量赋值,传递,特有的就是可以调用


    var f0 func(n int) int
    func f1(n int) int {
        return n*n
    }
    func f2(n int) int {
        return n+n
    }
    func f3(n,m int) int {
        return m*n
    }

    f := f1
    fmt.Println(reflect.TypeOf(f)) //func(int) int
    f = f2
    fmt.Println(f(10)) // 20
    //f = f3 报错,因为类型不同
    fmt.Println(reflect.TypeOf(f3)) //func(int, int) int

    fmt.Println(reflect.TypeOf(f0) == reflect.TypeOf(f1)) //true
    // fmt.Println(f2 == f1) 函数之间无法直接比较,所以不能作为 map 的 key,但是函数可以和 nil 比较

    //闭包
    func squares() func() int {
        var x int
        return func() int {
            x++
            return x * x
        }
    }
    f := squares()
    fmt.Println(f())  // 1
    fmt.Println(f())  // 4
    fmt.Println(f())  // 9
  • 命名函数只能在包级别声明,但是我们可以在任意地方声明函数变量或使用函数字面量(匿名函数)
  • 函数的零值是 nil,如果调用 nil 函数变量,会宕机

defer


    func def() string{
    defer fmt.Print("1")
    defer fmt.Print("2")
    defer fmt.Print("3")
    return "ok"

    def() //321
}

正常情况下,defer 修饰的语句会在 return 执行之后,逆序执行(堆),如果发生宕机,会在执行完 defer 后关闭程序
- 使用 os.Exit() 立即退出,则 defer 不会被执行
- 使用 panic 则 defer 会被执行

猜你喜欢

转载自blog.csdn.net/weixin_39653200/article/details/80903215