在 Go 语言中,函数被称为一等公民(First-Class Citizens),意味着函数可以像其他数据类型(如整数、字符串、结构体等)一样作为变量传递、返回、赋值等。这使得 Go 在编程时具备了极大的灵活性。
1、函数概念了解
函数的本质
- 函数本质上是定义的一段代码块,在编译后被转换为若干条指令。
构成要素
- 函数由语句块、函数名称、参数列表和返回值组成,是组织代码的最小单元,用于实现特定功能。
1.1、函数的作用
代码封装
- 函数是结构化编程中对代码进行封装的基本方式,通常按照功能组织一段代码。
减少冗余
- 函数封装的核心目的是为了复用代码,从而减少重复,实现更高效的开发。
提升可维护性
- 使用函数能让代码结构更加简洁美观,逻辑清晰,从而提高代码的可读性和可维护性。
1.2、函数分类
常用的内建函数
1.len
- 返回切片、数组、字符串、map 或通道的长度。
2.cap
- 返回切片或通道的容量。
3.new
- 分配内存并返回指向该内存的指针,初始化为零值。
4.make
- 用于创建并初始化切片、map 或通道的内存。
5.copy
- 将源切片的内容复制到目标切片,返回复制的元素数量。
6.append
- 向切片末尾添加元素,返回一个新的切片。
7.delete
- 从 map 中删除指定键及其对应的值。
8.complex
- 构造一个复数,由实部和虚部组成。
9.real
- 返回复数的实部。
10.imag
- 返回复数的虚部。
11.panic
- 引发一个运行时错误,程序进入崩溃或恢复模式。
12.recover
- 捕获由 panic 引发的错误,用于恢复程序的正常执行。
13.close
- 关闭通道,表示不再向该通道发送数据。
- 库函数:如 math.Ceil() 等,提供内置的功能封装,直接调用即可。
- 第三方函数:由第三方库提供的函数,需要了解其使用方法、参数传递(入参和出参)、以及文档或代码阅读。
- 自定义函数:由开发者使用 func 关键字自行定义,以实现特定的逻辑功能。
1.3、main函数了解
func main(){} 是程序的入口函数
- 在 Go 语言中,main 函数是程序的起点,所有的执行逻辑都会从这里开始。
Go 编译后的代码是二进制文件
- Go 编译器会将代码编译为适合当前操作系统的二进制指令,生成的可执行文件可以存储在持久化设备(如硬盘)上。
操作系统如何执行二进制文件
- 操作系统会读取这个文件,将其加载到内存中,并根据二进制指令构建一个进程。
OS 从哪里开始执行指令?(了解)
1.Go 程序的执行流程
- 操作系统并不会直接从 main 函数开始执行。实际上,编译后的程序包含一些启动代码(启动函数),用于完成运行时的初始化,如内存分配、goroutine 调度器的启动等。
2.执行顺序
- 程序的第一条执行指令并不是 main 函数的内容,而是由 Go 编译器插入的一些初始化逻辑。
当这些初始化任务完成后,程序会跳转到 main 函数并开始执行开发者编写的逻辑。
3.开发者关注点
- 对于开发者来说,重点是自己编写的代码逻辑。从 Go 的启动代码到执行 main 函数的这一过程是透明的,开发者无需关心底层的实现,只需专注于 main 函数的实现即可。
2、函数定义
2.1.函数的结构
func <函数名>([参数列表]) [返回值列表] {
// 函数体
}
2.2.函数定义规范
1.函数名
- 定义函数的标识符,应遵循命名规范,做到见名知意。
2.参数列表
- 用于传递数据给函数,参数是函数类型的重要组成部分。
3.返回值
- 函数执行后的结果输出,可以有零个或多个返回值。
4.函数的命名规范
- 遵循标识符规则,由字母、数字、下划线组成,不能以数字开头,区分大小写。
- 见名知意,名称应直观描述函数功能,避免含糊不清。
5.函数的类型
- 函数是数据结构的一种,它是 Go 中的一种大类型。
- 函数的具体类型,由函数的形参列表和返回值类型决定。
6.函数的作用
- 将一段代码封装在一起,方便编译成可执行的指令块。
- 提高代码的可读性和复用性,减少重复代码。
7. 函数名的本质
- 函数名是一个标识符,本质上是字符串。
- 符合标识符规范的函数名,可以在程序中唯一地标识和调用该函数。
2.3.参数列表(Parameter List)
- 参数列表决定了函数在调用时需要传递的参数数量和类型。
- 参数可以是 0个、1个或多个。
1.无参函数
定义:函数不需要任何参数输入。
func add() {} // 定义无参函数
add() // 调用无参函数
2.单参函数
- 形式参数(形参):用于在定义时占位,描述调用时将会传递的值。
func add(x int) {} // 定义单参函数,形参 x 为占位参数
add(5) // 调用时,5 是实际参数(实参)
3.多参函数
•可以传递多个参数,通过逗号分隔:
func add(x int, y int) {} // 多参函数
add(5, 10) // 调用函数时传递两个实参
2.4. 返回值列表
返回值是函数执行后的输出,可以是 0个、1个或多个:
无返回值
func display() {} // 定义无返回值函数
单返回值
func getValue() int { return 42 } // 返回一个整型值
多返回值:(在其他Java语言中,多返回值可能并不直接支持,通常需要通过数组或对象等方式来模拟实现。 Go 语言中,直接支持多返回值功能,使代码更加简洁和直观。)
func getValues() (int, string) { return 42, "hello" } // 返回多个值
2.5.函数复用
函数定义 一次,可以复用 多次,提升代码效率和组织性:
func add(x int, y int) int {
return x + y
}
func main() {
result1 := add(3, 5) // 第一次调用
result2 := add(10, 20) // 第二次调用
}
3、函数调用
3.1. 函数调用的基本概念
• 调用方式:
函数名() // 调用函数,执行其封装的功能和指令
•函数调用时,实际执行函数体内的代码。
3.2. 实际参数(实参)
定义:函数调用时传递给函数的具体参数,称为实际参数(实参)。
匹配规则:实参需要和形参数量、顺序、类型匹配。
func add(x int, y int) int {
return x + y
}
result := add(3, 5) // 实参 3 和 5 传递给形参 x 和 y
3.3.传参过程
定义:调用函数时,将实参传递给形参,函数内部使用形参完成计算或操作。
调用和返回值:
func display() {
fmt.Println("Hello, world!")
}
display() // 调用函数,无需处理返回值
//单返回值:
result := add(4, 5) // 调用函数,将返回值赋给变量
//多返回值:
func divide(x, y int) (int, int) {
return x / y, x % y
}
quotient, remainder := divide(10, 3) // 使用多个变量接收返回值
3.4. 函数调用的赋值过程
先执行右侧,函数被调用,执行其内部逻辑,直到返回结果。
再赋值左侧,将返回值赋给左侧的变量。
t := add(4, 5) // 调用 add 函数,等待返回值完成后再赋值给 t
赋值注意事项:
display() // 正确
t := display() // 错误:无返回值无法赋值
result := divide(10, 3) // 错误:返回多个值用一个变量接收
quotient, remainder := divide(10, 3) // 正确
3.5. 同步调用
- 函数调用为 同步操作:必须等函数执行完成,返回结果后才能进行后续操作。
t := add(4, 5) // 等待 add 函数执行完毕
fmt.Println(t) // 打印返回值 t
3.6. 多次调用的独立性
- 同一个函数可以多次调用,每次调用互不影响。
fmt.Println(add(2, 3)) // 输出 5
fmt.Println(add(4, 6)) // 输出 10
3.7. 调用的基本原则
- 函数调用前,函数必须被定义,否则会导致编译错误:
// 正确示例
func add(x int, y int) int {
return x + y
}
result := add(4, 5) // 调用时,函数已被定义
8. 好习惯好习惯:
在调用函数时,确保函数已经被正确定义。
本篇文章主要介绍了 Go 语言中函数的基本概念,重点帮助你理清 Go 函数的结构与使用方式,为进一步深入学习和实践 Go 函数的应用打下基础。如果你是 Go 语言的初学者,还不熟悉函数的使用,不必担心。掌握了函数的基本原理后,我将继续分享更多的函数编程技巧,帮助你逐步提升并熟练应用这些技能。
欢迎阅读,希望这篇文章能对你有所帮助。