项目结构与代码组织
1. 标准Go项目布局
参考Golang标准项目布局:
myproject/
├── api/ # API协议定义(Swagger, protobuf)
├── assets/ # 静态资源文件
├── build/ # 构建脚本和Dockerfile
├── cmd/ # 主应用程序入口
│ └── myapp/ # 主程序包
│ └── main.go # 主程序入口
├── configs/ # 配置文件模板或默认配置
├── deployments/ # 部署配置(k8s, nomad)
├── docs/ # 设计文档
├── examples/ # 示例代码
├── githooks/ # Git钩子
├── init/ # 系统初始化脚本
├── internal/ # 私有应用程序代码
│ ├── app/ # 应用层
│ ├── domain/ # 领域层
│ └── infrastructure/ # 基础设施层
├── pkg/ # 可复用的公共库
├── scripts/ # 各种脚本
├── test/ # 测试工具和测试数据
├── third_party/ # 第三方工具和代码
├── web/ # Web应用特定组件
├── go.mod # Go模块定义
├── go.sum # Go模块校验
├── Makefile # 构建管理
└── README.md # 项目说明
2. 分层架构设计
清晰的分层架构
internal/
├── app/ # 应用层(用例)
│ ├── handlers/ # HTTP处理器
│ ├── services/ # 业务服务
│ └── workers/ # 后台任务
├── domain/ # 领域层
│ ├── models/ # 领域模型
│ ├── repositories/ # 仓储接口
│ └── services/ # 领域服务
└── infrastructure/ # 基础设施层
├── db/ # 数据库访问
├── cache/ # 缓存实现
├── queue/ # 消息队列
└── config/ # 配置加载
依赖关系
HTTP Handler → Application Service → Domain Service → Repository → DB
3. 模块化组织
按功能模块组织
internal/
├── user/ # 用户模块
│ ├── handler.go # HTTP处理器
│ ├── service.go # 业务逻辑
│ ├── repository.go # 数据访问
│ └── model.go # 数据模型
├── order/ # 订单模块
│ ├── handler.go
│ ├── service.go
│ ├── repository.go
│ └── model.go
└── product/ # 产品模块
├── handler.go
├── service.go
├── repository.go
└── model.go
模块间通信
// 通过接口定义模块边界
type UserRepository interface {
FindByID(id string) (*User, error)
Save(user *User) error
}
// 实现可以独立替换
type MySQLUserRepository struct {
db *sql.DB
}
func (r *MySQLUserRepository) FindByID(id string) (*User, error) {
// 数据库查询实现
}
4. 配置管理
使用Viper管理配置
import "github.com/spf13/viper"
type Config struct {
Database struct {
Host string
Port int
Username string
Password string
}
Server struct {
Port int
}
}
func LoadConfig(path string) (Config, error) {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(path)
if err := viper.ReadInConfig(); err != nil {
return Config{}, err
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
return Config{}, err
}
return config, nil
}
环境变量覆盖
# config.yaml
database:
host: localhost
port: 3306
# 通过环境变量覆盖
export APP_DATABASE_HOST=mysql.prod
export APP_DATABASE_PORT=3307
// 自动绑定环境变量
viper.AutomaticEnv()
viper.SetEnvPrefix("app")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
5. 文档与代码生成
Swagger文档生成
// main.go
// @title My API
// @version 1.0
// @description This is a sample server.
// @host localhost:8080
// @BasePath /api/v1
func main() {
r := gin.Default()
// 路由定义
r.GET("/users/:id", getUser)
// Swagger
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run(":8080")
}
// @Summary 获取用户
// @Description 通过ID获取用户详情
// @ID get-user-by-id
// @Produce json
// @Param id path string true "用户ID"
// @Success 200 {object} User
// @Router /users/{id} [get]
func getUser(c *gin.Context) {
// 实现...
}
Wire依赖注入生成
// provider.go
var UserSet = wire.NewSet(
ProvideUserRepository,
ProvideUserService,
ProvideUserHandler,
)
func ProvideUserRepository(db *sql.DB) *MySQLUserRepository {
return &MySQLUserRepository{db: db}
}
func ProvideUserService(repo UserRepository) *UserService {
return &UserService{repo: repo}
}
func ProvideUserHandler(service *UserService) *UserHandler {
return &UserHandler{service: service}
}
// wire.go
func InitializeUserHandler(db *sql.DB) (*UserHandler, error) {
wire.Build(
UserSet,
)
return &UserHandler{}, nil
}
提示:良好的项目结构应该随着项目规模的增长而演进。从简单开始,在需要时逐步引入更复杂的结构。
