Go编程语言:支持并发、垃圾回收的编译型系统级编程语言!本文主要是按照无闻的《Go 编程基础》开源视频学习并记录笔记。
一、函数function
1、基本概念
函数是基本的代码块,用于执行一个任务。Go 语言最少有个 main() 函数
。函数声明告诉了编译器函数的名称,返回类型,和参数
。
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的函数个数。
2、函数定义
函数定义格式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
函数定义解析:
-
func
:函数由 func 开始声明 -
function_name
:函数名称,函数名和参数列表一起构成了函数签名。 -
parameter list
:参数列表,参数就像一个占位符
,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数
。参数是可选
的,也就是说函数也可以不包含参数。 -
return_types
:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。 -
函数体
:函数定义的代码集合。
示例:
/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
/* 声明局部变量 */
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
3、函数特性
- Go 函数
不支持
嵌套、重载和默认参数 - Go 函数
支持
无需声明原型、不定长度变参、多返回值、命名返回值参数、匿名函数、闭包 - 定义函数使用关键字
func
,且左大括号不能另起一行 函数也可以作为一种类型使用
ackage main
import "fmt"
func main() {
A(1, 2, 3, 4 ,5)
}
// ... 不定长变参
func A(a ...int) {
fmt.Println(a)
}
输出:
➜ myfirstgo go run func.go
[1 2 3 4 5]
不定长变参特性:
1、不可以在不定长变参后边添加其他参数 func b(a ...int, b string)
, 这种写法是错误
的
2、不定长参数可以放在其他参数后边 func b(b string, a ...int)
4、匿名函数
func main() {
// 将一个函数赋值一个变量,该变量是函数类型
a := func(){
fmt.Println("匿名函数")
}
// 调用
a()
}
5、闭包
/**
* 闭包函数
*
* 该闭包函数接收一个int型参数,其返回值是函数类型
*
*/
func closure(x int) func(int) int {
fmt.Println("%p\n", &x)
return func (y int) int {
fmt.Println("%p\n", &x)
fmt.Println(x)
fmt.Println(y)
return x + y
}
}
func main() {
f := closure(10);
fmt.Println(f(1))
fmt.Println(f(2))
}
打印结果:
➜ myfirstgo go run func.go
%p
0xc42000e228
%p
0xc42000e228
10
1
11
%p
0xc42000e228
10
2
12
➜ myfirstgo
6、defer
- defer 的执行方式类似其他语言中的
析构函数
,在函数体执行结束后按照调用顺序的相反顺序
逐个执行 - 即使函数发生
严重错误
也会执行 - 支持匿名函数的调用
- 常用于
资源清理、文件关闭、解锁以及记录时间
等操作 - 通过与匿名函数配合可在return之后
修改
函数计算结果 - 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址
- Go没有异常机制,但有
panic/recover
模式来处理错误 -
Panic
可以在任何地方引发,但recover
只有在 defer 调用的函数中有效
简单的测试:
func main() {
fmt.Println("a")
defer fmt.Println("b")
defer fmt.Println("c")
}
上边的执行会打印什么结果呢? 会打印:a b c 吗?
让我们实际执行一下:
myfirstgo go run func.go
a
c
b
实际打印的结果为:a c b
defer 的执行方式类似其他语言中的
析构函数
,在函数体执行结束后按照调用顺序的相反顺序
逐个执行
使用闭包
func main() {
for i := 0; i < 3; i++ {
// defer 普通调用
// defer fmt.Println(i) // 打印 2 1 0
// 使用闭包,引用局部变量
defer func () {
fmt.Println(i)
}()
}
}
打印结果:
➜ myfirstgo go run func.go
3
3
3
panic 使用示例:
func main() {
A()
B()
C()
}
func A() {
fmt.Println("FUNC A")
}
func B() {
// 匿名函数,如果没有参数,则末尾需要使用括号
defer func() {
if err := recover(); err != nil {
fmt.Println("Recover is B")
}
}()
panic("B panic")
}
func C() {
fmt.Println("FUNC C")
}
打印结果:
➜ myfirstgo go run func.go
FUNC A
Recover is B
FUNC C
➜ myfirstgo
有疑问加站长微信联系(非本文作者)