Files
golang/golang-learning/08-packages/01-creating-packages.go
2025-08-24 13:01:09 +08:00

666 lines
23 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
01-creating-packages.go - Go 语言包创建详解
学习目标:
1. 理解 Go 语言包的概念和作用
2. 掌握包的创建和组织方式
3. 学会包的命名规范和最佳实践
4. 了解包的可见性规则
5. 掌握包的文档编写
知识点:
- 包的基本概念和作用
- 包的创建和组织
- 包的命名规范
- 导出和未导出标识符
- 包的文档注释
- 包的初始化
*/
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"
)
func main() {
fmt.Println("=== Go 语言包创建详解 ===\\n")
// 演示包的基本概念
demonstratePackageBasics()
// 演示包的组织结构
demonstratePackageOrganization()
// 演示包的命名规范
demonstratePackageNaming()
// 演示可见性规则
demonstrateVisibilityRules()
// 演示包的文档
demonstratePackageDocumentation()
// 演示包的初始化
demonstratePackageInitialization()
// 演示实际包创建示例
demonstratePracticalPackageCreation()
}
// demonstratePackageBasics 演示包的基本概念
func demonstratePackageBasics() {
fmt.Println("1. 包的基本概念:")
// 包的基本概念
fmt.Printf(" 包的基本概念:\\n")
fmt.Printf(" - 包是 Go 语言组织代码的基本单位\\n")
fmt.Printf(" - 每个 Go 文件都必须属于一个包\\n")
fmt.Printf(" - 包提供了命名空间和封装机制\\n")
fmt.Printf(" - 包可以被其他包导入和使用\\n")
fmt.Printf(" - main 包是程序的入口点\\n")
// 包的作用
fmt.Printf(" 包的作用:\\n")
fmt.Printf(" 1. 代码组织:将相关功能组织在一起\\n")
fmt.Printf(" 2. 命名空间:避免命名冲突\\n")
fmt.Printf(" 3. 封装性:控制代码的可见性\\n")
fmt.Printf(" 4. 重用性:便于代码重用和分享\\n")
fmt.Printf(" 5. 模块化:支持大型项目的模块化开发\\n")
// 包的类型
fmt.Printf(" 包的类型:\\n")
fmt.Printf(" 1. main 包:可执行程序的入口\\n")
fmt.Printf(" 2. 库包:提供功能给其他包使用\\n")
fmt.Printf(" 3. 标准库包Go 官方提供的包\\n")
fmt.Printf(" 4. 第三方包:社区开发的包\\n")
fmt.Printf(" 5. 内部包:项目内部使用的包\\n")
// 包声明
fmt.Printf(" 包声明:\\n")
fmt.Printf(" - 每个 Go 文件的第一行必须是包声明\\n")
fmt.Printf(" - 格式package 包名\\n")
fmt.Printf(" - 同一目录下的所有 .go 文件必须属于同一个包\\n")
fmt.Printf(" - 包名通常与目录名相同(但不是必须的)\\n")
// 示例包声明
fmt.Printf(" 示例包声明:\\n")
packageExamples := []string{
"package main // 可执行程序",
"package utils // 工具包",
"package http // HTTP 相关功能",
"package database // 数据库操作",
"package config // 配置管理",
}
for _, example := range packageExamples {
fmt.Printf(" %s\\n", example)
}
fmt.Println()
}
// demonstratePackageOrganization 演示包的组织结构
func demonstratePackageOrganization() {
fmt.Println("2. 包的组织结构:")
// 项目结构示例
fmt.Printf(" 典型的项目结构:\\n")
fmt.Printf(" myproject/\\n")
fmt.Printf(" ├── main.go // 主程序\\n")
fmt.Printf(" ├── go.mod // 模块定义\\n")
fmt.Printf(" ├── README.md // 项目说明\\n")
fmt.Printf(" ├── cmd/ // 命令行程序\\n")
fmt.Printf(" │ └── server/\\n")
fmt.Printf(" │ └── main.go\\n")
fmt.Printf(" ├── pkg/ // 公共库\\n")
fmt.Printf(" │ ├── config/\\n")
fmt.Printf(" │ │ └── config.go\\n")
fmt.Printf(" │ └── utils/\\n")
fmt.Printf(" │ └── helper.go\\n")
fmt.Printf(" ├── internal/ // 内部包\\n")
fmt.Printf(" │ ├── auth/\\n")
fmt.Printf(" │ │ └── auth.go\\n")
fmt.Printf(" │ └── database/\\n")
fmt.Printf(" │ └── db.go\\n")
fmt.Printf(" ├── api/ // API 相关\\n")
fmt.Printf(" │ ├── handlers/\\n")
fmt.Printf(" │ │ └── user.go\\n")
fmt.Printf(" │ └── middleware/\\n")
fmt.Printf(" │ └── auth.go\\n")
fmt.Printf(" ├── models/ // 数据模型\\n")
fmt.Printf(" │ ├── user.go\\n")
fmt.Printf(" │ └── product.go\\n")
fmt.Printf(" ├── services/ // 业务逻辑\\n")
fmt.Printf(" │ ├── user.go\\n")
fmt.Printf(" │ └── product.go\\n")
fmt.Printf(" ├── tests/ // 测试文件\\n")
fmt.Printf(" │ └── integration/\\n")
fmt.Printf(" └── docs/ // 文档\\n")
fmt.Printf(" └── api.md\\n")
// 包组织原则
fmt.Printf(" 包组织原则:\\n")
fmt.Printf(" 1. 按功能分组:相关功能放在同一个包中\\n")
fmt.Printf(" 2. 单一职责:每个包应该有明确的职责\\n")
fmt.Printf(" 3. 依赖管理:避免循环依赖\\n")
fmt.Printf(" 4. 接口分离:定义清晰的包接口\\n")
fmt.Printf(" 5. 层次结构:建立合理的包层次\\n")
// 目录命名规范
fmt.Printf(" 目录命名规范:\\n")
fmt.Printf(" - 使用小写字母\\n")
fmt.Printf(" - 使用短而有意义的名称\\n")
fmt.Printf(" - 避免使用下划线和连字符\\n")
fmt.Printf(" - 使用复数形式(如 handlers, models\\n")
fmt.Printf(" - 避免使用 Go 关键字\\n")
// 特殊目录
fmt.Printf(" 特殊目录:\\n")
fmt.Printf(" - cmd/: 存放可执行程序的源码\\n")
fmt.Printf(" - pkg/: 存放可以被外部应用使用的库代码\\n")
fmt.Printf(" - internal/: 存放私有应用和库代码\\n")
fmt.Printf(" - vendor/: 存放依赖包的副本\\n")
fmt.Printf(" - testdata/: 存放测试数据\\n")
fmt.Println()
}
// demonstratePackageNaming 演示包的命名规范
func demonstratePackageNaming() {
fmt.Println("3. 包的命名规范:")
// 命名规则
fmt.Printf(" 包命名规则:\\n")
fmt.Printf(" 1. 使用小写字母\\n")
fmt.Printf(" 2. 简短而有意义\\n")
fmt.Printf(" 3. 避免使用下划线\\n")
fmt.Printf(" 4. 不要使用复数形式\\n")
fmt.Printf(" 5. 避免与标准库冲突\\n")
// 好的包名示例
fmt.Printf(" 好的包名示例:\\n")
goodNames := []string{
"http", // 简短明了
"json", // 广为人知的缩写
"url", // 常用缩写
"time", // 简单直接
"crypto", // 清晰的功能描述
"database", // 完整但不冗长
"config", // 简洁的功能描述
"auth", // 常用缩写
}
for _, name := range goodNames {
fmt.Printf(" %s\\n", name)
}
// 不好的包名示例
fmt.Printf(" 不好的包名示例:\\n")
badNames := map[string]string{
"HTTP": "使用了大写字母",
"http_client": "使用了下划线",
"utils": "太通用,没有明确含义",
"helpers": "使用了复数形式",
"mypackage": "没有描述功能",
"data_base": "使用了下划线",
"user_service": "使用了下划线",
"common": "太通用",
}
for name, reason := range badNames {
fmt.Printf(" %s - %s\\n", name, reason)
}
// 包名与导入路径
fmt.Printf(" 包名与导入路径:\\n")
fmt.Printf(" - 包名是 package 声明中的名称\\n")
fmt.Printf(" - 导入路径是 import 语句中的路径\\n")
fmt.Printf(" - 包名通常是导入路径的最后一部分\\n")
fmt.Printf(" - 但包名和目录名可以不同\\n")
// 示例
fmt.Printf(" 示例:\\n")
fmt.Printf(" 导入路径: github.com/user/project/pkg/database\\n")
fmt.Printf(" 包名: package database\\n")
fmt.Printf(" 使用: database.Connect()\\n")
fmt.Println()
}
// demonstrateVisibilityRules 演示可见性规则
func demonstrateVisibilityRules() {
fmt.Println("4. 可见性规则:")
// 可见性基本规则
fmt.Printf(" 可见性基本规则:\\n")
fmt.Printf(" - 首字母大写:导出(公开),可被其他包访问\\n")
fmt.Printf(" - 首字母小写:未导出(私有),只能包内访问\\n")
fmt.Printf(" - 适用于:函数、变量、常量、类型、方法、字段\\n")
// 导出标识符示例
fmt.Printf(" 导出标识符示例:\\n")
exportedExamples := []string{
"func Add(a, b int) int", // 导出函数
"var MaxSize = 1000", // 导出变量
"const DefaultTimeout = 30", // 导出常量
"type User struct { Name string }", // 导出类型
"func (u User) GetName() string", // 导出方法
}
for _, example := range exportedExamples {
fmt.Printf(" %s // 导出\\n", example)
}
// 未导出标识符示例
fmt.Printf(" 未导出标识符示例:\\n")
unexportedExamples := []string{
"func add(a, b int) int", // 未导出函数
"var maxSize = 1000", // 未导出变量
"const defaultTimeout = 30", // 未导出常量
"type user struct { name string }", // 未导出类型
"func (u user) getName() string", // 未导出方法
}
for _, example := range unexportedExamples {
fmt.Printf(" %s // 未导出\\n", example)
}
// 结构体字段的可见性
fmt.Printf(" 结构体字段的可见性:\\n")
fmt.Printf(" type User struct {\\n")
fmt.Printf(" Name string // 导出字段\\n")
fmt.Printf(" Email string // 导出字段\\n")
fmt.Printf(" age int // 未导出字段\\n")
fmt.Printf(" address string // 未导出字段\\n")
fmt.Printf(" }\\n")
// 方法的可见性
fmt.Printf(" 方法的可见性:\\n")
fmt.Printf(" func (u *User) GetName() string { // 导出方法\\n")
fmt.Printf(" return u.Name\\n")
fmt.Printf(" }\\n")
fmt.Printf("\\n")
fmt.Printf(" func (u *User) setAge(age int) { // 未导出方法\\n")
fmt.Printf(" u.age = age\\n")
fmt.Printf(" }\\n")
// 接口的可见性
fmt.Printf(" 接口的可见性:\\n")
fmt.Printf(" type Reader interface { // 导出接口\\n")
fmt.Printf(" Read() ([]byte, error) // 导出方法\\n")
fmt.Printf(" }\\n")
fmt.Printf("\\n")
fmt.Printf(" type writer interface { // 未导出接口\\n")
fmt.Printf(" write([]byte) error // 未导出方法\\n")
fmt.Printf(" }\\n")
// 可见性设计原则
fmt.Printf(" 可见性设计原则:\\n")
fmt.Printf(" 1. 最小暴露:只导出必要的标识符\\n")
fmt.Printf(" 2. 稳定接口:导出的接口应该稳定\\n")
fmt.Printf(" 3. 清晰命名:导出的标识符应该有清晰的名称\\n")
fmt.Printf(" 4. 文档完整:导出的标识符应该有完整的文档\\n")
fmt.Printf(" 5. 向后兼容:避免破坏性的接口变更\\n")
fmt.Println()
}
// demonstratePackageDocumentation 演示包的文档
func demonstratePackageDocumentation() {
fmt.Println("5. 包的文档:")
// 文档注释规则
fmt.Printf(" 文档注释规则:\\n")
fmt.Printf(" 1. 紧邻声明之前,中间不能有空行\\n")
fmt.Printf(" 2. 以被注释的标识符名称开头\\n")
fmt.Printf(" 3. 使用完整的句子\\n")
fmt.Printf(" 4. 第一句话应该是简洁的摘要\\n")
fmt.Printf(" 5. 可以包含示例代码\\n")
// 包文档示例
fmt.Printf(" 包文档示例:\\n")
fmt.Printf(" /*\\n")
fmt.Printf(" Package math 提供基本的数学函数和常量。\\n")
fmt.Printf("\\n")
fmt.Printf(" 这个包包含了常用的数学运算函数,如三角函数、\\n")
fmt.Printf(" 对数函数、指数函数等。所有函数都经过优化,\\n")
fmt.Printf(" 适用于高性能计算场景。\\n")
fmt.Printf("\\n")
fmt.Printf(" 示例用法:\\n")
fmt.Printf(" result := math.Sqrt(16) // 计算平方根\\n")
fmt.Printf(" angle := math.Sin(math.Pi / 2) // 计算正弦值\\n")
fmt.Printf(" */\\n")
fmt.Printf(" package math\\n")
// 函数文档示例
fmt.Printf(" 函数文档示例:\\n")
fmt.Printf(" // Add 计算两个整数的和。\\n")
fmt.Printf(" //\\n")
fmt.Printf(" // 参数 a 和 b 可以是任意整数,包括负数。\\n")
fmt.Printf(" // 返回值是 a 和 b 的算术和。\\n")
fmt.Printf(" //\\n")
fmt.Printf(" // 示例:\\n")
fmt.Printf(" // sum := Add(3, 4) // 返回 7\\n")
fmt.Printf(" // sum := Add(-1, 1) // 返回 0\\n")
fmt.Printf(" func Add(a, b int) int {\\n")
fmt.Printf(" return a + b\\n")
fmt.Printf(" }\\n")
// 类型文档示例
fmt.Printf(" 类型文档示例:\\n")
fmt.Printf(" // User 表示系统中的用户。\\n")
fmt.Printf(" //\\n")
fmt.Printf(" // User 包含用户的基本信息,如姓名、邮箱等。\\n")
fmt.Printf(" // 所有字段都是必需的,不能为空。\\n")
fmt.Printf(" type User struct {\\n")
fmt.Printf(" // Name 是用户的全名\\n")
fmt.Printf(" Name string\\n")
fmt.Printf("\\n")
fmt.Printf(" // Email 是用户的邮箱地址,必须是有效格式\\n")
fmt.Printf(" Email string\\n")
fmt.Printf(" }\\n")
// 常量和变量文档
fmt.Printf(" 常量和变量文档示例:\\n")
fmt.Printf(" // MaxRetries 是操作失败时的最大重试次数。\\n")
fmt.Printf(" const MaxRetries = 3\\n")
fmt.Printf("\\n")
fmt.Printf(" // DefaultTimeout 是网络操作的默认超时时间。\\n")
fmt.Printf(" var DefaultTimeout = 30 * time.Second\\n")
// 文档生成
fmt.Printf(" 文档生成:\\n")
fmt.Printf(" - 使用 go doc 命令查看文档\\n")
fmt.Printf(" - 使用 godoc 工具生成 HTML 文档\\n")
fmt.Printf(" - 文档会自动发布到 pkg.go.dev\\n")
// 文档示例命令
fmt.Printf(" 文档查看命令:\\n")
fmt.Printf(" go doc utils // 查看包文档\\n")
fmt.Printf(" go doc utils.Add // 查看函数文档\\n")
fmt.Printf(" go doc -all utils // 查看所有文档\\n")
fmt.Println()
}
// demonstratePackageInitialization 演示包的初始化
func demonstratePackageInitialization() {
fmt.Println("6. 包的初始化:")
// 初始化顺序
fmt.Printf(" 包初始化顺序:\\n")
fmt.Printf(" 1. 导入的包先初始化\\n")
fmt.Printf(" 2. 包级别变量按声明顺序初始化\\n")
fmt.Printf(" 3. init 函数按出现顺序执行\\n")
fmt.Printf(" 4. main 函数最后执行\\n")
// init 函数特点
fmt.Printf(" init 函数特点:\\n")
fmt.Printf(" - 函数名必须是 init\\n")
fmt.Printf(" - 不能有参数和返回值\\n")
fmt.Printf(" - 不能被显式调用\\n")
fmt.Printf(" - 一个包可以有多个 init 函数\\n")
fmt.Printf(" - 在包被导入时自动执行\\n")
// init 函数示例
fmt.Printf(" init 函数示例:\\n")
fmt.Printf(" package config\\n")
fmt.Printf("\\n")
fmt.Printf(" import (\\n")
fmt.Printf(" \\\"fmt\\\"\\n")
fmt.Printf(" \\\"os\\\"\\n")
fmt.Printf(" )\\n")
fmt.Printf("\\n")
fmt.Printf(" var AppName string\\n")
fmt.Printf("\\n")
fmt.Printf(" func init() {\\n")
fmt.Printf(" fmt.Println(\\\"初始化配置包\\\")\\n")
fmt.Printf(" AppName = os.Getenv(\\\"APP_NAME\\\")\\n")
fmt.Printf(" if AppName == \\\"\\\" {\\n")
fmt.Printf(" AppName = \\\"DefaultApp\\\"\\n")
fmt.Printf(" }\\n")
fmt.Printf(" }\\n")
// 包级别变量初始化
fmt.Printf(" 包级别变量初始化:\\n")
fmt.Printf(" var (\\n")
fmt.Printf(" // 简单初始化\\n")
fmt.Printf(" MaxSize = 1000\\n")
fmt.Printf("\\n")
fmt.Printf(" // 函数调用初始化\\n")
fmt.Printf(" StartTime = time.Now()\\n")
fmt.Printf("\\n")
fmt.Printf(" // 复杂初始化\\n")
fmt.Printf(" Config = loadConfig()\\n")
fmt.Printf(" )\\n")
// 初始化依赖
fmt.Printf(" 初始化依赖:\\n")
fmt.Printf(" - Go 会自动分析变量间的依赖关系\\n")
fmt.Printf(" - 按依赖顺序进行初始化\\n")
fmt.Printf(" - 循环依赖会导致编译错误\\n")
// 初始化示例
fmt.Printf(" 初始化示例:\\n")
fmt.Printf(" var (\\n")
fmt.Printf(" a = b + 1 // 依赖 b\\n")
fmt.Printf(" b = 2 // 先初始化\\n")
fmt.Printf(" c = a + b // 依赖 a 和 b\\n")
fmt.Printf(" )\\n")
fmt.Printf(" // 初始化顺序b -> a -> c\\n")
// 初始化最佳实践
fmt.Printf(" 初始化最佳实践:\\n")
fmt.Printf(" 1. 保持 init 函数简单\\n")
fmt.Printf(" 2. 避免在 init 中进行复杂操作\\n")
fmt.Printf(" 3. 不要依赖 init 函数的执行顺序\\n")
fmt.Printf(" 4. 优先使用包级别变量初始化\\n")
fmt.Printf(" 5. 处理初始化可能的错误\\n")
fmt.Println()
}
// demonstratePracticalPackageCreation 演示实际包创建示例
func demonstratePracticalPackageCreation() {
fmt.Println("7. 实际包创建示例:")
// 分析现有包结构
fmt.Printf(" 分析现有包结构:\\n")
// 获取当前目录
currentDir, err := os.Getwd()
if err != nil {
fmt.Printf(" 获取当前目录失败: %v\\n", err)
return
}
// 分析 utils 包
utilsPath := filepath.Join(currentDir, "utils")
if _, err := os.Stat(utilsPath); err == nil {
fmt.Printf(" 找到 utils 包: %s\\n", utilsPath)
analyzePackage(utilsPath)
} else {
fmt.Printf(" utils 包不存在: %v\\n", err)
}
// 包创建步骤
fmt.Printf(" 包创建步骤:\\n")
fmt.Printf(" 1. 创建包目录\\n")
fmt.Printf(" 2. 编写包声明\\n")
fmt.Printf(" 3. 定义导出的接口\\n")
fmt.Printf(" 4. 实现功能函数\\n")
fmt.Printf(" 5. 添加文档注释\\n")
fmt.Printf(" 6. 编写测试文件\\n")
fmt.Printf(" 7. 创建示例代码\\n")
// 包设计原则
fmt.Printf(" 包设计原则:\\n")
fmt.Printf(" 1. 单一职责:每个包应该有明确的职责\\n")
fmt.Printf(" 2. 高内聚:包内元素应该紧密相关\\n")
fmt.Printf(" 3. 低耦合:包间依赖应该最小化\\n")
fmt.Printf(" 4. 稳定接口:导出接口应该稳定\\n")
fmt.Printf(" 5. 易于使用API 应该简单直观\\n")
// 包的版本管理
fmt.Printf(" 包的版本管理:\\n")
fmt.Printf(" - 使用语义化版本号(如 v1.2.3\\n")
fmt.Printf(" - 主版本号:不兼容的 API 变更\\n")
fmt.Printf(" - 次版本号:向后兼容的功能增加\\n")
fmt.Printf(" - 修订版本号:向后兼容的问题修复\\n")
// 包的发布
fmt.Printf(" 包的发布:\\n")
fmt.Printf(" 1. 创建 Git 仓库\\n")
fmt.Printf(" 2. 添加 go.mod 文件\\n")
fmt.Printf(" 3. 编写 README.md\\n")
fmt.Printf(" 4. 添加许可证文件\\n")
fmt.Printf(" 5. 创建版本标签\\n")
fmt.Printf(" 6. 推送到代码仓库\\n")
fmt.Println()
}
// analyzePackage 分析包的结构
func analyzePackage(packagePath string) {
fmt.Printf(" 分析包: %s\\n", packagePath)
// 遍历包目录中的 Go 文件
err := filepath.Walk(packagePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 只处理 .go 文件
if !strings.HasSuffix(path, ".go") {
return nil
}
// 解析 Go 文件
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
if err != nil {
fmt.Printf(" 解析文件 %s 失败: %v\\n", path, err)
return nil
}
// 分析文件内容
fmt.Printf(" 文件: %s\\n", filepath.Base(path))
fmt.Printf(" 包名: %s\\n", node.Name.Name)
// 统计导出和未导出的标识符
var exportedFuncs, unexportedFuncs int
var exportedTypes, unexportedTypes int
var exportedVars, unexportedVars int
for _, decl := range node.Decls {
switch d := decl.(type) {
case *ast.FuncDecl:
if d.Name.IsExported() {
exportedFuncs++
} else {
unexportedFuncs++
}
case *ast.GenDecl:
for _, spec := range d.Specs {
switch s := spec.(type) {
case *ast.TypeSpec:
if s.Name.IsExported() {
exportedTypes++
} else {
unexportedTypes++
}
case *ast.ValueSpec:
for _, name := range s.Names {
if name.IsExported() {
exportedVars++
} else {
unexportedVars++
}
}
}
}
}
}
fmt.Printf(" 导出函数: %d, 未导出函数: %d\\n", exportedFuncs, unexportedFuncs)
fmt.Printf(" 导出类型: %d, 未导出类型: %d\\n", exportedTypes, unexportedTypes)
fmt.Printf(" 导出变量: %d, 未导出变量: %d\\n", exportedVars, unexportedVars)
return nil
})
if err != nil {
fmt.Printf(" 分析包失败: %v\\n", err)
}
}
/*
运行这个程序:
go run 01-creating-packages.go
学习要点:
1. 包是 Go 语言组织代码的基本单位
2. 包提供了命名空间和封装机制
3. 包的可见性通过标识符首字母大小写控制
4. 包应该有清晰的文档和合理的组织结构
5. 包的设计应该遵循单一职责和高内聚低耦合原则
包的基本概念:
1. 每个 Go 文件都必须属于一个包
2. 同一目录下的所有 .go 文件必须属于同一个包
3. 包名通常与目录名相同
4. main 包是程序的入口点
5. 包提供了代码的模块化和重用机制
包的组织原则:
1. 按功能分组:相关功能放在同一个包中
2. 单一职责:每个包应该有明确的职责
3. 依赖管理:避免循环依赖
4. 接口分离:定义清晰的包接口
5. 层次结构:建立合理的包层次
可见性规则:
1. 首字母大写:导出(公开),可被其他包访问
2. 首字母小写:未导出(私有),只能包内访问
3. 适用于函数、变量、常量、类型、方法、字段
4. 最小暴露原则:只导出必要的标识符
5. 稳定接口:导出的接口应该稳定
包的文档:
1. 文档注释紧邻声明之前
2. 以被注释的标识符名称开头
3. 使用完整的句子
4. 第一句话应该是简洁的摘要
5. 可以包含示例代码
包的初始化:
1. 导入的包先初始化
2. 包级别变量按依赖顺序初始化
3. init 函数按出现顺序执行
4. main 函数最后执行
5. 每个包只初始化一次
最佳实践:
1. 使用清晰简洁的包名
2. 遵循 Go 的命名规范
3. 编写完整的文档注释
4. 保持包的职责单一
5. 设计稳定的公共接口
6. 避免循环依赖
7. 合理组织包的结构
注意事项:
1. 包名应该小写且简洁
2. 避免使用通用名称如 util、common
3. 不要在包名中使用下划线
4. 包的导入路径应该唯一
5. 考虑包的向后兼容性
*/