函数
函数是基本的代码块,用于执行一个任务。可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。函数声明告诉了编译器函数的名称,返回类型,和参数。
函数定义
Go 语言函数定义格式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
- func:函数由 func 开始声明
- function_name:函数名称,函数名和参数列表一起构成了函数签名。
- parameter
list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。 - return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下
return_types 不是必须的。 - 函数体:函数定义的代码集合。
实例:
以下实例为 max() 函数的代码,该函数传入两个整型参数 num1 和 num2,并返回这两个参数的最大值:
/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
/* 声明局部变量 */
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
值传递与引用传递
因为在go语言中存在值类型与引用类型,所以在函数参数进行传递时也要注意这个问题。
- 值传递是指在函数调用过程中将实参拷贝一份到函数中,这样在函数中如果对参数进行修改,将不会影响到实参。
- 引用传递是指在函数调用过程中将实参的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实参。
如果想要函数可以直接修改参数的值,那么我们可以用指针传递,将变量的地址作为参数传递到函数中。
实例:
func paramFunc(a int, b *int, c []int) {
a = 100
*b = 100
c[1] = 100
fmt.Println("paramFunc:")
fmt.Println(a)
fmt.Println(*b)
fmt.Println(c)
}
func main() {
a := 1
b := 1
c := []int{1, 2, 3}
paramFunc(a, &b, c)
fmt.Println("main:")
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}
输出如下:
paramFunc:
100
100
[1 100 3]
main:
1
100
[1 100 3]
变长函数
实例:
func main() {
slice := []int{7, 9, 3, 5, 1}
x := min(slice...)
fmt.Printf("The minimum is: %d", x)
}
func min(s ...int) int {
if len(s) == 0 {
return 0
}
min := s[0]
for _, v := range s {
if v < min {
min = v
}
}
return min
}
上面这段代码直接将切片作为参数也能实现同样的效果,但是变长参数更多的是为了参数不确定的情况,例如fmt包中的Printf函数设计如下:
func Printf(format string, a …interface{}) (n int, err error) {
return Fprintf(os.Stdout, format, a…)
}
函数返回多个值
实例:
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("Hello", "Wrold")
fmt.Println(a, b)
}
输出如下:
Hello World
命名返回值
实例:
func div(a, b float64) (result float64, err error) {
if b == 0 {
return 0, errors.New("被除数不能等于0")
}
result = a / b
return
}
注:即使只有一个命名返回值,也需要使用()括起来。
匿名函数
匿名函数如其名字一样,是一个没有名字的函数,除了没有名字外其他地方与正常函数相同。匿名函数可以直接调用,保存到变量,作为参数或者返回值。
实例:
func main() {
f := func() string {
return "hello world"
}
fmt.Println(f())
}
闭包
闭包可以解释为一个函数与这个函数外部变量的一个封装。粗略的可以理解为一个类,类里面有变量和方法,其中闭包所包含的外部变量对应着类中的静态变量。
实例:
func add() func(int) int {
n := 10
str := "string"
return func(x int) int {
n = n + x
str += strconv.Itoa(x)
fmt.Print(str, " ")
return n
}
}
func main() {
f := add()
fmt.Println(f(1))
fmt.Println(f(2))
fmt.Println(f(3))
f = add()
fmt.Println(f(1))
fmt.Println(f(2))
fmt.Println(f(3))
}
输出如下:
string1 11
string12 13
string123 16
string1 11
string12 13
string123 16
用闭包实现斐波那契数列:
package main
import "fmt"
func fibonacci() func() int {
back1, back2 := 0, 1
return func() int {
temp := back1
back1, back2 = back2, (back1 + back2)
return temp
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
输出如下;
0
1
1
2
3
5
8
13
21
34
参考:
datawhalechina
菜鸟教程