🐸 青蛙编程网
首页 / Go / Go 基础 / 4. 函数与包

4. 函数与包

这是什么:函数 = 起好名字的一段代码,可以收参数、交结果;包(package) = 把函数按目录打包,跨文件互相调用。

为什么用:上一章数据存进了变量,可代码全堆在 main 里,重复逻辑抄三遍、改一处就得改三处。用函数打包逻辑、用包分组文件,代码才长得下去。

如何用:先写一个最普通的 add 函数,再体验 Go 招牌的多返回值 (result, error),最后把函数分到不同包里用 import 串起来。

4.1 基本函数

func add(a int, b int) int {
    return a + b
}
// 同类型连续参数可简写 a, b int

4.2 多返回值(Go 的招牌)

错误处理线性可读的基石——结果 + 错误一起返回:

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("除数不能为 0")
    }
    return a / b, nil        // nil = 「没有错误」
}

func main() {
    r, err := divide(10, 2)
    if err != nil {
        fmt.Println("出错:", err)
        return
    }
    fmt.Println(r)
}
5

官方模式:调用函数先接 err、先判断 err——本章贯通第 6 章 error 处理。

4.3 命名返回值与 defer

func calc() (sum int) {
    defer fmt.Println("函数结束啦")   // defer:函数 return 前才执行
    sum = 42
    return                            // 命名返回:自动返回 sum
}

defer 常用来「收尾」(关文件、解锁),后进先出。

4.4 可变参数与匿名函数

func sumAll(nums ...int) int {     // ...int 可变参数
    total := 0
    for _, n := range nums {       // _ 丢弃 index
        total += n
    }
    return total
}

sumAll(1, 2, 3)                    // 6
go func() { fmt.Println("并发!") }()  // 匿名函数直接起 goroutine

_ 是弃位符:不想要的值统统用 _ 接,避免「未使用变量」报错。

4.5 包(package)与目录

hello/
├── go.mod
├── main.go        (package main,入口)
└── utils/
    └── math.go    (package utils)
// utils/math.go
package utils

func Double(x int) int { return x * 2 }   // 大写开头 = 可被外部访问(导出)
func hidden() {}                          // 小写开头 = 私有
// main.go
import "hello/utils"

fmt.Println(utils.Double(21))    // 42

要点:

  • import 使用模块路径(go.mod 里的模块名 + 目录)
  • 大写 = 公开,小写 = 私有(Go 用这招代替 public/private)
go build ./...    # 编译整个项目

4.6 动手改

  1. 写 max(nums ...int) 返回最大值,塞进 utils 并在 main 调用
  2. 用 defer 顺序体会「后进先出」
  3. 故意调私有 utils.hidden() 看编译报错

4.7 小结

  • 多返回 (result, error),调用方先看 err
  • defer 收尾栈;_ 弃位
  • 大写导出、小写私有,import 按模块路径

下一章:结构体与方法 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。