Golang函数

1. 函数定义

1.1 golang函数特点
  • 无需声明原型。
    • 支持不定 变参。
    • 支持多返回值。
    • 支持命名返回参数。 
    • 支持匿名函数和闭包。
    • 函数也是一种类型,一个函数可以赋值给变量。

    • 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数。
    • 不支持 重载 (overload) 
    • 不支持 默认参数 (default parameter)

​ 函数声明包含一个函数名,参数列表,返回列表和函数体。参数列表,返回列表可以省略。

package main

import "fmt"

func test(fn func() int) int {
    return fn()
}
// 定义函数类型。
type FormatFunc func(s string, x, y int) string 

func format(fn FormatFunc, s string, x, y int) string {
    return fn(s, x, y)
}

func main() {
    s1 := test(func() int { return 100 }) // 直接将匿名函数当参数。

    s2 := format(func(s string, x, y int) string {
        return fmt.Sprintf(s, x, y)
    }, "%d, %d", 10, 20)

    println(s1, s2)
}

2. 参数

​ 函数定义时的参数称为函数的形参(定义在函内部使用的局部变量);

​ 调用函数传递过来的变量称为函数的实参。实参可以通过两种方式传递:值传递和引用传递;

package main

import "fmt"

// 值传递
func valueTest(x, y int) (int, int) {
	x, y = y, x
	return x, y
}

// 引用传递
/*
map、slice、chan、指针、interface默认以引用的方式传递
*/
func quoteTest(x, y *int) (*int, *int) {
	*x, *y = *y, *x
	return x, y
}

// 不定参数传值
func manyTest(args ...int) {

}

func main() {
	x := 0
	y := 1
	valueTest(x, y)
	fmt.Println(x, y)
	quoteTest(&x, &y)
	fmt.Println(x, y)
}

3. 返回值

​ GoLang的返回值可以被命名,返回值的名称应具有一定意义,可读性强。

​ 没有参数的return语句返回各个返回变量当前值。

4. 匿名函数

​ 匿名函数由一个不带函数名的函数声明和函数体组成。匿名函数的优越性在于可以直接使用函数内部的变量,不必声明。

5. 闭包、递归

5.1 闭包

​ 闭包是由函数及其相关引用环境组合而成的实体(闭包=函数+引用环境)。

// 闭包复制的是原对象指针
func a() func() int {
   i := 0
   b := func() int {
      i++
      fmt.Println(i)
      return i
   }
   return b
}
5.2 递归

​ 递归:程序在运行过程中调用自己,就叫做递归函数。

构成递归的两个必要条件:

​ 1.子问题与原始问题为同样的事,且更为简单。

​ 2.不能无限调用自身,必须有函数出口。

func factorial(i int) int {
    if i <= 1 {
        return 1
    }
    return i * factorial(i-1)
}
斐波那契数列(Fibonacci)
package main

import "fmt"

func fibonaci(i int) int {
    if i == 0 {
        return 0
    }
    if i == 1 {
        return 1
    }
    return fibonaci(i-1) + fibonaci(i-2)
}

func main() {
    var i int
    for i = 0; i < 10; i++ {
        fmt.Printf("%d\n", fibonaci(i))
    }
}

6. 延时调用(defer)

后进先出(堆栈)

defer特性:
    1. 关键字 defer 用于注册延迟调用。
    2. 这些调用直到 return 前才被执。因此,可以用来做资源清理。
    3. 多个defer语句,按先进后出的方式执行。
    4. defer语句中的变量,在defer声明时就决定了。
defer用途:
 1. 关闭文件句柄
    2. 锁资源释放
    3. 数据库连接释放

7. 异常处理

​ Golang没有结构化异常,使用panic抛出异常,recover捕获异常(一般在defer中通过recover捕获异常)。

panic:
1.内置函数
2.函数F中书写了panic语句,会终止之后要执行的代码,在panic所在函数F内如果存在要执行的defer函数列表,逆序执行
3.返回函数F的调用者G,在G中,调用函数F语句之后的代码不会执行,如果函数G中存在要执行的defer函数列表,逆序执行
4.知道goroutine整个推出,并报告错误
recover:
1.内置函数
2.用来控制一个groutine的panicking行为,捕获panic,从而影响应用的行为
3.一般建议的调用:
	(1.defer函数中,通过recover终止一个goroutine的panicking过程,从而恢复正常代码的执行
	(2.通过panic传递的error
注意
1.利用recover处理panic指令,defer必须放在panic定义之前。recover只有在defer调用的函数中才有效,否则当panic时,recover无法捕获panic,无法防止panic扩散。
2.recover处理异常后,逻辑并不会恢复到panic那个点去,函数跑到defer之后的那个点
3.多个defer会形成defer栈,后定义的defer语句会最先被调用
error:

​ 标准库 errors.New 和 fmt.Errorf 函数用于创建实现 error 接口的错误对象。通过判断错误对象实例来确定具体错误类型。

导致关键流程出现不可修复性错误的使用 panic,其他使用 error。

8. 测试

1. 单元测试
类型格式作用
测试函数函数名前缀为Test测试程序的一些逻辑行为是否正确
基准函数函数名前缀为Benchmark测试函数的性能
示例函数函数名前缀为Example为文档提供示例文档
2. 压力测试

​ 压力测试用例必须遵循如下格式,其中XXX可以是任意字母数字的组合,但是首字母不能是小写字母

func BenchmarkXXX(b *testing.B) { ... }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值