Go两周入门系列-函数

2023-09-26 14:33:20 浏览数 (1)

本章介绍函数的定义和用法

  • • 函数支持0个或者多个参数
  • • 函数支持0个或者多个返回值

1. 基本函数定义

语法:

代码语言:javascript复制
func 函数名(参数列表) (返回值类型列表) {
}

例子:

代码语言:javascript复制
package main

import "fmt"

// 定义add函数,接受两个int参数,返回值是int类型
func add(x int, y int) int {
return x   y
}

func main() {
// 调用函数add, 然后调用Println函数打印返回值
fmt.Println(add(42, 13))
}

2. 返回多个值的函数

go语言的函数允许返回多个值

例子:

代码语言:javascript复制
package main

import "fmt"

// 定义swap函数,接受x,y两个参数,swap函数的作用是交换两个参数值
// 连续多个参数的类型一致的话,可以用逗号分隔变量,仅在最后一个变量书写数据类型
// 返回两个string类型的值
func swap(x, y string) (string, string) {
// 返回多个值,用逗号分隔
return y, x
}

func main() {
// 调用swap函数,并且接受两个返回值,按顺序传递给a和b变量
a, b := swap("hello", "world")
fmt.Println(a, b)
}

3. 返回命名参数值

我们可以给函数返回值定义命名参数。

例子:

代码语言:javascript复制
package main

import "fmt"

// 定义split函数
// 定义x,y两个int类型的返回值参数
func split(sum int) (x, y int) {
// 给x返回值参数赋值
x = sum * 4 / 9
// 给y返回值参数赋值
y = sum - x
// 直接return,就可以返回x,y参数值
return
}

func main() {
fmt.Println(split(17))
}

4.忽略参数返回值

函数可以返回多个值,有时候我们只想要其中一个值,可以通过 _ 下划线符号,忽略返回值。

接上面的例子

代码语言:javascript复制
// 忽略掉第一个返回值,接受第二个返回值
_, y := split(17)

// 接受第一个返回值,忽略第二个返回值
x, _ := split(17)

4. defer语句

defer是延迟调用语句,延迟调用指的是被defer修饰的函数调用,在父函数执行接结束的时候才会执行defer修饰的函数。

4.1. 基本用法

例子:

代码语言:javascript复制
package main

import "fmt"

func main() { // 父函数
// 延迟调用Println函数,也就是延迟打印world字符串
defer fmt.Println("world")

// 打印hello
fmt.Println("hello")
}

执行代码输出:helloworld

执行流程说明:

使用defer修饰fmt.Println("world"),并不会立即执行Println函数,所以不会打印world。

fmt.Println("hello")语句会立即执行,输出hello

这个时候main函数执行结束,因为main函数是父函数,这个时候会执行 defer fmt.Println("world") 函数,输出world。

说明:父函数是一个相对概念,调用函数的函数,就是父函数。

4.2. defer调用栈

如果在同一个函数中,存在多个defer修饰的延迟调用函数,那么执行顺序是怎么样的?

例子:

代码语言:javascript复制
package main

import "fmt"

func main() {
fmt.Println("counting")

for i := 0; i < 10; i   {
// 延迟打印 i
defer fmt.Println(i)
}

// 会比上面的defer语句先执行
fmt.Println("done")
}

执行后输出:

代码语言:javascript复制
counting
done
9
8
7
6
5
4
3
2
1
0

执行流程,延迟调用函数,会保存在一个调用栈中,执行的时候反序执行,所以看到上面例子,数字倒序输出。

5.闭包(匿名函数)

没有函数名的函数,我们叫做匿名函数,通常也叫做闭包,它拥有可以引用定义闭包上下文环境变量的特性。

简单的闭包例子:

代码语言:javascript复制
// 定义一个闭包,并将闭包函数赋值给变量f
f := func() {
fmt.Println("我是闭包函数")
}

// 通过变量f调用闭包函数
f();

闭包引用上下文环境变量的例子:

代码语言:javascript复制
package main

import (
"fmt"
)

func main() {
// 计数器变量
count := 0

// 定义一个闭包,并将闭包函数赋值给变量f
f := func() {
// 因为闭包函数是在main函数中定义的,所以可以引用main函数定义的变量
count  
fmt.Println("count=", count)
}

// 通过变量f调用闭包函数
f();
f();
f();
}

输出:

代码语言:javascript复制
count= 1
count= 2
count= 3

上下文环境,指的就是定义闭包函数的函数内的局部作用域。

参考:https://www.tizi365.com/

0 人点赞