【go语言】包 package 与 Go Modules

包是 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
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容