包是 Go 语言组织代码的基本单元,同一个目录下的所有源文件必须属于同一个包。包化让代码可以复用,也控制了标识符的可见性。
1. 包的定义与导入
每个源文件开头用 package 声明包名,main 包是特殊的,它编译为可执行程序:
// utils/math.go
package utils
func Add(a, b int) int { return a + b }
// main.go
package main
import "example.com/demo/utils"
func main() {
fmt.Println(utils.Add(1, 2)) // 3
}
标识符的可见性由首字母大小写决定:首字母大写可被其他包访问(导出),小写只能包内使用。这个规则让注释之外的可见性声明都不需要了。
2. 导入的几种形式
import "fmt" // 普通导入
import u "example.com/demo/utils" // 起别名
import . "example.com/demo/utils" // 点导入:直接用 Add,不推荐
import _ "image/png" // 空白导入:只执行包的 init
导入却未使用会编译错误,这是 Go 强制保持代码整洁的设计。空白导入主要为了触发包的 init 函数,例如注册图片解码器。
3. init 函数
每个包可以有多个 init 函数,它们在 main 之前自动执行,顺序是:被依赖的包先初始化。init 适合做配置解析、注册表填充等准备工作:
package db
var config map[string]string
func init() {
config = loadConfig()
}
4. Go Modules 依赖管理
现代 Go 项目用模块(module)管理依赖。go mod init 创建模块,go mod tidy 根据代码自动增删依赖:
go mod init example.com/demo
go get github.com/gin-gonic/gin@v1.9.1
go mod tidy
go mod vendor # 依赖拷贝到本地 vendor 目录
go.sum 记录依赖的校验和保证可重现构建,go.mod 声明模块名和依赖版本。导入路径 = 模块名 + 包目录路径。
5. 包设计的建议
包名用小写单词、简短且不用下划线;包提供能力而不是堆砌工具函数;避免循环导入,出现循环时把公共部分抽到第三个包或用接口解耦。internal 目录下的包只能被其父目录中的代码导入,适合放私有实现。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END









暂无评论内容