第11讲 包测试
本讲义根据视频实际讲解内容整理
一、本讲概述
本讲讲解了 Go 语言中包(Package)和文件的概念。大项目不可能只用一个文件,需要通过包来实现模块化、封装和代码重用。老师演示了如何创建包、导入包,以及包的导出规则、作用域、多返回值等知识点。
二、为什么需要包
"大的项目,肯定不可能是一个文件玩吧。"
- 之前所有代码都写在一个文件中
- 大项目需要分层、分目录管理代码
- 包(Package)的目的:支持模块化、封装、单独编译和代码重用
- 类似于 Java 中的包和模块
三、包的基本概念
3.1 包的源文件
- 一个包的源代码保存在一个或多个
.go后缀的文件中 - 通常一个包所在的目录路径就是包的导入路径
3.2 独立的命名空间
- 每个包对应一个独立的名字空间
- 例如,
unicode包中的Decode和其他包中的Decode是不同的 - 外部引用时需要通过
包名.函数名的方式访问
3.3 导出规则(核心)
"如果一个名字是大写字母开头的,那么该名字是可导出的。"
| 首字母 | 可见性 | 说明 |
|---|---|---|
| 大写 | 可导出(公开) | 外部包可以访问 |
| 小写 | 不可导出(私有) | 仅包内部可访问 |
四、创建和导入包
4.1 创建包
老师在课堂上演示了创建一个自定义包:
Go
// 目录结构
// myproject/
// main.go
// utils/
// utils.go
// utils/utils.go
package utils
func Add(a int, b int) int { // 大写开头,可导出
return a + b
}
func helper() { // 小写开头,不可导出
// 仅包内可用
}
4.2 导入包
Go
// main.go
package main
import (
"fmt"
"myproject/utils" // 导入自定义包
)
func main() {
result := utils.Add(3, 5) // 通过 包名.函数名 调用
fmt.Println(result) // 8
}
4.3 老师演示中遇到的问题
老师在演示时遇到了一些实际问题:
- 包名大小写问题:包名统一用小写,不要大写
- 版本差异问题:Go 模块路径需要正确配置,有时需要在
go.mod中加上模块名 - go mod 管理:使用
go mod init初始化模块
五、包的初始化
5.1 初始化顺序
"包的初始化,首先是解决包变量的依赖程序,第一个初始化,第二个初始化,第三个初始化。"
- 包初始化时,会先解决变量依赖关系
- 按照依赖顺序依次初始化
5.2 子包的创建
老师演示了在包下面再创建子包:
TEXT
myproject/
main.go
utils/
utils.go
utils/sub/
sub.go
六、作用域(Scope)
6.1 := 的使用限制
老师重点讲解了一个容易出错的地方:
"
:=(短变量声明)能不能写到函数外面呢?不能!"
Go
package main
import "fmt"
var a int = 10 // ✅ 函数外用 var 声明,正确
// b := 20 // ❌ 函数外不能用 :=,编译错误
func main() {
a = 10
fmt.Println(a) // 10
b := 20 // ✅ 函数内可以用 :=
fmt.Println(b) // 20
}
6.2 作用域规则总结
| 位置 | 声明方式 | 说明 |
|---|---|---|
| 函数内 | := 或 var |
都可以 |
| 函数外(包级) | 只能用 var |
不能用 := |
"在外面我们不能用这种方式(:=),必须用 var 的形式,在里面就没事。"
七、多返回值与下划线
7.1 函数返回多个值
老师演示了 Go 函数可以返回多个值:
Go
package main
import "fmt"
func calculate(a int, b int) (int, int) {
return a + b, a - b
}
func main() {
sum, diff := calculate(10, 3)
fmt.Println("和:", sum) // 和: 13
fmt.Println("差:", diff) // 差: 7
}
7.2 用下划线忽略返回值
如果不需要某个返回值,用 _(下划线)忽略:
Go
sum, _ := calculate(10, 3) // 只需要和,忽略差
fmt.Println("和:", sum) // 和: 13
"下划线就是把结果给它省略了,不需要的值用下划线表示。"
7.3 函数声明格式
老师强调了函数声明的格式:
Go
func 函数名(参数列表) (返回类型) {
// 函数体
}
- 参数类型在参数名后面
- 返回类型在参数列表后面
- 多返回值用括号包裹
八、后续内容预告
老师在讲义末尾提到了后续将要学习的内容:
| 类别 | 内容 |
|---|---|
| 基本数据类型 | 整数、浮点数等 |
| 复合数据类型 | 数组、切片、Map |
| 结构体和 JSON | 后续使用较多 |
| 函数 | 递归、多返回值 |
"结构体和 JSON 可能用得比较多。"
九、小结
本讲涵盖了包和文件的核心知识:
- 包的作用:模块化、封装、代码重用
- 导出规则:大写字母开头 = 可导出,小写 = 私有
- 创建和导入包:通过目录组织包,用
import导入 - 作用域:
:=只能在函数内使用,函数外必须用var - 多返回值:Go 支持函数返回多个值,用
_忽略不需要的值