Go——函数签名和匿名函数

1、函数签名

函数类型又叫函数签名,一个函数的类型就是函数定义首行去掉函数名、参数名和{,可以使用fmt.Printf的"%T"格式化参数打印函数的类型。

package main

import "fmt"

func main() {
	fmt.Printf("%T\n", add) //func(int, int) int
}

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

两个函数类型相同的条件是:拥有相同的形参列表和返回值列表(列表元素的次序、个数和类型都相同),形参名可以不同。一下两个函数的函数类型完全一样。

func add(a,b int) int {return a + b}
func sub(x int, y int)(c int) { c = x - y; return c}

可以使用type定义函数类型,函数类型变量可以作为函数的参数或返回值。

package main

import "fmt"

func main() {
	a := do(add, 1, 2) //函数名add可以当做相同函数类型形参,不需要强制类型转换
	fmt.Println(a)     //3
	s := do(sub, 1, 2)
	fmt.Println(s) //-1
}

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

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

//定义一个函数类型,输入是两个int类型,返回值是一个int类型
type Op func(int, int) int

//定义一个函数,第一个参数是函数类型Op
func do(f Op, a, b int) int {
	return f(a, b) //函数类型变量可以直接用来进行函数调用
}

函数类型和map、slice、chan一样,实际函数类型变量和函数名都可以当作指针变量,该指针指向函数代码的开始位置。通常说函数类型变量是一种引用类型,未初始化的函数类型的变量的默认值是nil。

Go中函数是“第一公民”(first class)。有名函数的函数名可以看作函数类型的常量,可以直接使用函数名调用函数,也可以直接赋值给函数类型变量,后续通过该变量来调用该函数。

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



sum(3, 4) //直接调用
f := sum  //有名函数可以直接赋值给变量
i := f(1, 2)
fmt.Println(i) //3

2、匿名函数

G0提供两种函数:有名函数和匿名函数。匿名函数可以看作函数字面量,所有直接使用函数类型变量的地方都可以由匿名函数代替。匿名函数可以直接赋值给函数变量,可以当作实参,也可以作为返回值,还可以直接被调用。

package main

import "fmt"

func main() {
	//匿名函数直接被调用
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	sum(1, 2)

	//匿名函数作为实参
	doinput(func(x, y int) int {
		return x + y
	}, 1, 2)

	opFunc := wrap("add")
	re := opFunc(2, 3)
	fmt.Printf("%d\n", re)
}

//匿名函数被直接赋值函数变量
var sum = func(a, b int) int {
	return a + b
}

func doinput(f func(int, int) int, a, b int) int {
	return f(a, b)
}

//匿名函数作为返回值
func wrap(op string) func(int, int) int {
	switch op {
	case "add":
		return func(a, b int) int {
			return a + b
		}
	case "sub":
		return func(a, b int) int {
			return a - b
		}
	default:
		return nil
	}
}

你可能感兴趣的:(Go,golang,算法,开发语言)