Go语言-初学者日记(三):函数与方法
函数是 Go 程序的基础单元,方法是结构体的“超能力扩展包”。理解函数与方法的使用与内存行为,是写好 Go 程序的关键。
🧩 一、函数定义与调用
func sayHello(name string) string {
return "Hello, " + name
}
msg := sayHello("Gopher")
fmt.Println(msg)
- 使用
func
定义函数。 - 每个参数与返回值都必须明确标明类型。
- 支持类型合并,例如
(x, y int)
。
🧠 小贴士:
- 函数名首字母大写 → 可导出(其他包可访问)。
- 函数是 一等公民,可以赋值、传参、返回!
🔁 二、多返回值:Go 的“批发函数”
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为0")
}
return a / b, nil
}
调用方式:
result, err := divide(10, 2)
if err != nil {
fmt.Println("出错了:", err)
} else {
fmt.Println("结果是:", result)
}
📌 多返回值特别适合“结果 + 错误”的组合,也是 Go 的错误处理核心风格。
📦 三、命名返回值 & 空白标识符 _
🏷 命名返回值
func getUser() (name string, age int) {
name = "Alice"
age = 18
return // 自动返回 name 和 age
}
增加可读性,适合函数较长时使用。
🚮 空白标识符 _
_, err := divide(1, 0)
if err != nil {
fmt.Println("捕捉到错误")
}
- 用于忽略不想使用的值
- 常用于函数返回多个值但只关心其中之一
🧱 四、变参函数:支持不定数量参数
func sum(nums ...int) int {
total := 0
for _, v := range nums {
total += v
}
return total
}
调用方式:
fmt.Println(sum(1, 2, 3)) // 输出 6
也可以传入切片:
values := []int{1, 2, 3}
sum(values...) // 解包传参
🌀 五、函数也是值:匿名函数与闭包
匿名函数
greet := func(name string) {
fmt.Println("Hi,", name)
}
greet("Gopher")
闭包:函数引用外部变量
func counter() func() int {
i := 0
return func() int {
i++
return i
}
}
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
📌 闭包会“捕获并持有”其外层变量,即使函数返回后变量依然保留。
🏷️ 六、方法:结构体的专属技能
type User struct {
Name string
}
func (u User) SayHi() {
fmt.Println("Hi,我是", u.Name)
}
- 方法语法类似函数,但多了接收者
(u User)
- 用于给结构体添加行为(面向对象)
调用方式:
user := User{Name: "Gopher"}
user.SayHi()
☯️ 七、值接收者 vs 指针接收者
值接收者
func (u User) Rename(newName string) {
u.Name = newName // 实际不影响外部 user 变量
}
指针接收者
func (u *User) Rename(newName string) {
u.Name = newName // 可修改原结构体内容
}
调用时 Go 会自动推断:
user := User{Name: "Bob"}
user.Rename("Alice") // 自动转为 &user
🧠 使用建议:
需求 | 推荐接收者类型 |
---|---|
修改结构体字段 | 指针接收者 |
不修改、结构体很小 | 值接收者 |
实现接口(一般一致) | 统一指针或统一值接收者 |
💡 八、函数的内存行为与栈逃逸简析(进阶)
- 函数参数和局部变量默认分配在栈上,函数调用结束即释放。
- 若返回闭包或引用变量,变量可能逃逸到堆上。
func makePtr() *int {
x := 10
return &x // x 逃逸到堆上
}
使用 go build -gcflags="-m"
可查看逃逸分析信息:
go run -gcflags="-m" main.go
🧠 总结
特性 | 是否支持 | 示例说明 |
---|---|---|
多返回值 | ✅ | a, b := fn() |
命名返回值 | ✅ | return 自动返回 |
变参函数 | ✅ | func f(...T) |
匿名函数 | ✅ | f := func() {...} |
闭包捕获变量 | ✅ | return func() { i++ } |
方法绑定结构体 | ✅ | func (t T) Method() |
指针接收者修改 | ✅ | func (t *T) Set() |
🔨 推荐实战练习
- ✅ 写一个计算器高阶函数
operate(a, b int, op func(int, int) int)
- ✅ 实现
counter()
闭包,用于生成递增计数器 - ✅ 编写
User
结构体,添加方法Login()
、Logout()
、Rename()
- ✅ 实现
sum(...int)
变参函数 + 使用切片解包测试
🪧 下一篇预告
👉 Go语言-初学者日记(四):包与模块管理,从“Hello World”走向项目实战!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dtcms.com/a/115180.html
如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!