golang-基础-Go语言函数
Go语言的函数是构建程序逻辑的核心单元,具有强大的灵活性和多样性。以下从基础定义到高级特性,全面解析Go函数的设计、使用场景及示例代码。
一、函数基础定义
1.1 基本结构
Go函数使用 func
关键字定义,语法如下:
func 函数名(参数列表) (返回值列表) {
// 函数体
}
- 参数列表:可选,用于接收输入值,格式为
参数名 类型
。 - 返回值列表:可选,指定函数返回的值类型。若无返回值可省略。
- 函数体:实现具体逻辑的代码块。
示例:简单加法函数
func add(a int, b int) int {
return a + b
}
func main() {
sum := add(3, 5)
fmt.Println("Sum:", sum) // 输出: Sum: 8
}
二、参数传递方式
2.1 值传递
Go默认使用值传递,即传递参数的副本,函数内修改不会影响原始值。
func modifyValue(num int) {
num = 10
}
func main() {
x := 5
modifyValue(x)
fmt.Println(x) // 输出: 5(原始值未改变)
}
2.2 引用传递
通过指针实现引用传递,函数内修改会影响原始值。
func modifyReference(num *int) {
*num = 10
}
func main() {
y := 5
modifyReference(&y)
fmt.Println(y) // 输出: 10(原始值被修改)
}
三、返回值类型
3.1 单个返回值
func square(n int) int {
return n * n
}
3.2 多个返回值
Go支持返回多个值,常用于返回结果和错误信息。
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}
func main() {
quotient, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Quotient:", quotient) // 输出: Quotient: 5
}
}
3.3 命名返回值
为返回值命名,简化 return
语句。
func swap(a, b int) (x, y int) {
x = b
y = a
return // 直接返回命名值
}
四、特殊函数类型
4.1 变参函数
使用 ...T
语法接收不定数量的同类型参数。
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
func main() {
result := sum(1, 2, 3, 4, 5)
fmt.Println("Sum:", result) // 输出: Sum: 15
}
4.2 匿名函数
匿名函数无名称,可赋值给变量或立即执行。
// 赋值给变量
add := func(a, b int) int {
return a + b
}
fmt.Println(add(3, 4)) // 输出: 7
// 立即执行
result := func(a, b int) int {
return a * b
}(5, 6)
fmt.Println("Result:", result) // 输出: Result: 30
4.3 闭包
匿名函数可以捕获外部变量,形成闭包。
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
c := counter()
fmt.Println(c()) // 输出: 1
fmt.Println(c()) // 输出: 2
}
4.4 defer函数
defer
用于延迟执行函数调用,常用于资源释放。
func main() {
file, _ := os.Open("file.txt")
defer file.Close() // 确保文件关闭
// 读取文件...
}
五、适用场景
5.1 模块化编程
将复杂逻辑封装成函数,提高代码复用性。
// 计算矩形面积
func calculateArea(width, height int) int {
return width * height
}
5.2 错误处理
多返回值用于返回结果和错误信息。
func parseInput(s string) (int, error) {
return strconv.Atoi(s)
}
5.3 并发编程
函数作为goroutine执行,实现并发。
func worker(id int) {
fmt.Printf("Worker %d is working\n", id)
}
func main() {
for i := 0; i < 5; i++ {
go worker(i)
}
time.Sleep(time.Second) // 等待goroutine完成
}
5.4 资源管理
使用 defer
确保资源释放。
func readData() {
conn, _ := net.Dial("tcp", "example.com:80")
defer conn.Close()
// 使用conn...
}
5.5 高阶函数
函数可作为参数或返回值,实现高阶函数。
func apply(fn func(int) int, x int) int {
return fn(x)
}
func main() {
result := apply(func(n int) int {
return n * 2
}, 5)
fmt.Println(result) // 输出: 10
}
六、高级特性
6.1 init函数
init
函数在 main
函数前自动执行,用于包级初始化。
package main
import "fmt"
func init() {
fmt.Println("Initializing package...")
}
func main() {
fmt.Println("Main function started.")
}
6.2 包管理
- 导出函数:首字母大写的函数可被其他包访问。
- 包别名:使用
import
为包取别名。
import (
"fmt"
"math/rand"
mymath "myproject/mathutils" // 别名
)
func main() {
fmt.Println(mymath.Add(1, 2)) // 调用自定义包函数
}
6.3 内置函数
len()
:获取长度。new()
:分配值类型内存。make()
:分配引用类型内存(如map
、slice
、chan
)。
s := make([]int, 5) // 创建长度为5的slice
p := new(int) // 分配int指针
七、完整示例
示例1:多返回值与命名返回值
func calc(a, b int) (sum, diff int) {
sum = a + b
diff = a - b
return
}
func main() {
s, d := calc(10, 3)
fmt.Println("Sum:", s, "Difference:", d) // 输出: Sum: 13 Difference: 7
}
示例2:闭包与延迟执行
func logger(prefix string) func(string) {
return func(msg string) {
fmt.Printf("[%s] %s\n", prefix, msg)
}
}
func main() {
log := logger("INFO")
defer log("Function completed")
log("Processing started") // 输出: [INFO] Processing started
}
示例3:变参与匿名函数
func main() {
max := func(values ...int) int {
var m int
for _, v := range values {
if v > m {
m = v
}
}
return m
}
fmt.Println(max(3, 7, 1, 9)) // 输出: 9
}
八、总结
Go语言函数的特性包括:
- 简洁定义:通过
func
关键字声明。 - 灵活参数:支持值传递、引用传递、变参。
- 多返回值:适用于错误处理和多重结果返回。
- 闭包与高阶函数:提升代码复用性和功能性。
- 资源管理:
defer
机制确保资源释放。 - 包管理:通过首字母大小写控制可见性。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 软件从业者Hort
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果