包和模块
Go 语言的包系统是其组织代码的核心机制,而 Go Modules 是现代 Go 项目的依赖管理方式。
包(Package)
包的概念
包是 Go 语言中代码组织和复用的基本单位。每个 Go 文件都属于一个包。
go
package main // 包声明
import "fmt" // 导入包
func main() {
fmt.Println("Hello, World!")
}包声明
package main: 可执行程序的入口包package <name>: 库包,可以被其他包导入
导入包
go
// 单个导入
import "fmt"
// 多个导入
import (
"fmt"
"os"
"strings"
)
// 别名导入
import f "fmt"
f.Println("Hello")
// 点导入(不推荐)
import . "fmt"
Println("Hello")
// 空白导入(只执行 init 函数)
import _ "database/sql/driver"Go Modules
Go Modules 是 Go 1.11+ 引入的官方依赖管理工具。
初始化模块
bash
go mod init <module-name>这会创建 go.mod 文件:
go
module github.com/user/project
go 1.21
require (
github.com/go-zoox/zoox v1.x.x
)添加依赖
bash
# 自动添加依赖
go get github.com/go-zoox/zoox
# 指定版本
go get github.com/go-zoox/zoox@v1.x.x
# 最新版本
go get github.com/go-zoox/zoox@latestgo.mod 文件
go
module github.com/user/project
go 1.21
require (
github.com/go-zoox/zoox v1.x.x
github.com/stretchr/testify v1.8.4
)
require (
github.com/go-zoox/core-utils v1.x.x // indirect
)go.sum 文件
go.sum 文件包含依赖的校验和,用于验证依赖的完整性。
常用命令
bash
# 下载依赖
go mod download
# 整理依赖
go mod tidy
# 查看依赖
go list -m all
# 更新依赖
go get -u ./...
# 验证依赖
go mod verify包的可见性
Go 语言使用首字母大小写控制可见性:
go
// 公开(可被其他包访问)
func PublicFunction() {}
var PublicVariable = "public"
// 私有(只能在当前包内访问)
func privateFunction() {}
var privateVariable = "private"包的组织
标准项目结构
project/
├── go.mod
├── go.sum
├── main.go
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── config/
│ └── handler/
├── pkg/
│ ├── utils/
│ └── models/
└── api/
└── routes.gointernal 包
internal 目录下的包只能被父目录的包导入:
project/
├── internal/
│ └── auth/ # 只能被 project 下的包导入
└── pkg/
└── utils/ # 可以被任何包导入导入和导出
导出函数
go
// package math
package math
// Add 是导出的函数
func Add(a, b int) int {
return a + b
}
// subtract 是未导出的函数
func subtract(a, b int) int {
return a - b
}使用导出的函数
go
package main
import "github.com/user/project/math"
func main() {
result := math.Add(1, 2) // OK
// math.subtract(1, 2) // 错误:未导出
}init 函数
每个包可以有一个或多个 init 函数,在包被导入时自动执行:
go
package config
var Config map[string]string
func init() {
Config = make(map[string]string)
Config["env"] = "production"
}标准库介绍
常用标准库
fmt
格式化输入输出:
go
import "fmt"
fmt.Print("Hello")
fmt.Println("World")
fmt.Printf("Name: %s, Age: %d\n", name, age)os
操作系统接口:
go
import "os"
// 环境变量
os.Getenv("PATH")
os.Setenv("KEY", "value")
// 文件操作
os.Open("file.txt")
os.Create("file.txt")strings
字符串操作:
go
import "strings"
strings.Contains("hello", "ll")
strings.Split("a,b,c", ",")
strings.Join([]string{"a", "b"}, ",")
strings.TrimSpace(" hello ")net/http
HTTP 客户端和服务器:
go
import "net/http"
// HTTP 服务器
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
// HTTP 客户端
resp, err := http.Get("https://example.com")encoding/json
JSON 编码和解码:
go
import "encoding/json"
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
data, _ := json.Marshal(Person{Name: "Alice", Age: 30})
var p Person
json.Unmarshal(data, &p)time
时间处理:
go
import "time"
now := time.Now()
duration := time.Hour * 2
future := now.Add(duration)sync
同步原语:
go
import "sync"
var mutex sync.Mutex
var wg sync.WaitGroup
var once sync.Once创建自己的包
包结构
mypackage/
├── go.mod
├── math.go
└── utils.gomath.go
go
package mypackage
// Add 两个数相加
func Add(a, b int) int {
return a + b
}
// Multiply 两个数相乘
func Multiply(a, b int) int {
return a * b
}使用包
go
package main
import "github.com/user/mypackage"
func main() {
sum := mypackage.Add(1, 2)
product := mypackage.Multiply(3, 4)
}版本管理
语义化版本
Go Modules 使用语义化版本(Semantic Versioning):
v1.2.3: 主版本.次版本.修订版本v0.1.0: 开发版本v1.0.0-beta.1: 预发布版本
版本选择
go
require (
github.com/go-zoox/zoox v1.x.x // 精确版本
github.com/go-zoox/zoox ^1.0.0 // 兼容版本
github.com/go-zoox/zoox latest // 最新版本
)完整示例
go
// go.mod
module github.com/user/mylib
go 1.21
// math/math.go
package math
// Add 返回两个整数的和
func Add(a, b int) int {
return a + b
}
// Subtract 返回两个整数的差
func Subtract(a, b int) int {
return a - b
}
// main.go
package main
import (
"fmt"
"github.com/user/mylib/math"
)
func main() {
sum := math.Add(10, 5)
diff := math.Subtract(10, 5)
fmt.Printf("和: %d, 差: %d\n", sum, diff)
}最佳实践
- 使用有意义的包名:简短、小写、单数形式
- 避免循环依赖:合理组织包结构
- 使用 internal 包:限制内部包的可见性
- 保持包的精简:每个包应该有单一职责
- 使用 go mod tidy:定期整理依赖
下一步
接下来我们将学习:
