Go:函数、defer

一、函数可赋值给一个变量

示例1:

package main

import "fmt"

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

func main() {
	xx := add
	fmt.Println(xx(10, 10)) // 20
}

示例2:

package main

import "fmt"

// opFunc为自定义的类型名字,这里它是一个函数,接收两个值,返回一个值
type opFunc func(int, int) int

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

// op为变量名字,op_func为自己定义的类型
func operator(op opFunc, a, b int) int {
	return op(a, b)
}

func main() {
	xx := add
	result := operator(xx, 10, 10)
	fmt.Println(result) // 20
}

示例3:示例2也可以写成如下,示例2中为什么使用type自定义类型?这样可以让函数没那么繁琐,更简洁。

package main

import "fmt"

// opFunc为自定义的类型名字,这里它是一个函数,接收两个值,返回一个值
//type opFunc func(int, int) int

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

// op为变量名字,op_func为自己定义的类型
func operator(op func(int, int) int, a, b int) int {
	return op(a, b)
}

func main() {
	xx := add
	result := operator(xx, 10, 10)
	fmt.Println(result) // 20
} 

二、可变参数

// 0个或多个参数
func sumArgs(args …int) int {
}
// 1个或多个参数
func sumArgs(a int, args …int) int {
}
// 2个或多个参数
func sumArgs(a int, b int, args …int) int {
}

注意:其中args是一个slice,我们可以通过args[index]依次访问所有参数,通过len(args)来判断传递参数的个数。

示例:

package main

import "fmt"

func sumArgs(args ...int) int {
	sum := 0
	for i := range args {
		sum += args[i]
	}
	return sum
}

func main() {
	fmt.Println(sumArgs(1, 2, 3, 4, 5)) // 15
}

三、匿名函数

package main

import "fmt"

func add(a, b int) int {
	result := func(a1, b1 int) int {
		return a1 + b1
	}(a, b) // 定义时就调用
	return result
}

func main() {
	fmt.Println(add(10, 10)) // 20
}

或者:

package main

import "fmt"

func add(a, b int) int {
	result := func(a1, b1 int) int {
		return a1 + b1
	}
	return result(a, b)
}

func main() {
	fmt.Println(add(10, 10)) // 20
}

全局匿名函数:

package main

import "fmt"

var (
	//Func就是一个全局匿名函数
	Func = func(a, b int) int {
		return a * b
	}
)

func main() {
	result := Func(10, 10)
	fmt.Println(result)
}

四、defer用途

  • 当函数返回时,执行defer语句,因此,可以用来做资源清理;
  • 多个defer语句,按先进后出的方式执行;
  • defer语句中的变量,在defer声明时就决定了。

示例:

package main

import "fmt"

func test(a, b int) {
	defer fmt.Println(a)
	defer fmt.Println(b)
	tmp := a + b
	fmt.Println(tmp)
}

func main() {
	test(10, 20)
}

// 输出结果:
// 30
// 20
// 10

在 defer 将语句代码放入到栈时,也会将相关的值拷贝同时入栈:

package main

import "fmt"

func test(a, b int) {
	defer fmt.Println(a)
	defer fmt.Println(b)
	a++
	b++
	tmp := a + b
	fmt.Println(tmp)
}

func main() {
	test(10, 20)
}

// 输出结果:
// 32
// 20
// 10

defer的最主要价值是,当函数执行完毕后,可以及时的释放函数创建的资源(请看如下伪代码):

func test() {
	// 关闭文件资源
	file = openFile(文件名)
	defer file.close()
	// 其他代码
}

func test() {
	// 释放数据库支援
	conn = openDatabase()
	defer conn.close()
	// 其他代码
}
原文地址:https://www.cnblogs.com/believepd/p/10853928.html