Skip to content

6.1 项目结构 ​

标准项目布局 ​

project/
├── cmd/                    # 应用程序入口
│   ├── myapp/
│   │   └── main.go
│   └── migration/
│       └── main.go
├── internal/               # 私有包
│   ├── config/
│   ├── handler/
│   ├── service/
│   ├── repository/
│   └── models/
├── pkg/                    # 公共包
│   ├── logger/
│   ├── utils/
│   └── middleware/
├── api/                    # API 定义
│   ├── openapi.yaml
│   └── proto/
├── configs/                # 配置文件
├── scripts/                # 脚本文件
├── deployments/            # 部署配置
│   ├── Dockerfile
│   └── k8s/
├── test/                   # 测试文件
├── docs/                   # 文档
├── go.mod
├── go.sum
├── Makefile
└── README.md

cmd 目录示例 ​

go
// cmd/myapp/main.go
package main

import (
    "context"
    "flag"
    "os"
    "os/signal"
    "syscall"
    "time"

    "example.com/myapp/internal/config"
    "example.com/myapp/internal/handler"
    "example.com/myapp/pkg/logger"
)

var version = "dev"

func main() {
    // 命令行参数
    var configFile string
    flag.StringVar(&configFile, "config", "configs/config.yaml", "配置文件路径")
    flag.Parse()

    // 初始化日志
    log := logger.NewLogger()

    // 加载配置
    cfg, err := config.Load(configFile)
    if err != nil {
        log.Error("加载配置失败", "error", err)
        os.Exit(1)
    }

    // 初始化服务
    userService := service.NewUserService(cfg.Database)
    userHandler := handler.NewUserHandler(userService)

    // 启动服务器
    server := handler.NewServer(cfg.Server, userHandler)

    // 优雅关闭
    ctx, stop := signal.NotifyContext(context.Background(),
        os.Interrupt, syscall.SIGTERM)
    defer stop()

    go func() {
        <-ctx.Done()
        shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        defer cancel()
        server.Shutdown(shutdownCtx)
    }()

    if err := server.Start(); err != nil {
        log.Error("服务器启动失败", "error", err)
        os.Exit(1)
    }
}

配置管理 (viper) ​

go
import "github.com/spf13/viper"

type Config struct {
    Server   ServerConfig   `mapstructure:"server"`
    Database DatabaseConfig `mapstructure:"database"`
    JWT      JWTConfig      `mapstructure:"jwt"`
}

func Load(configPath string) (*Config, error) {
    v := viper.New()
    v.SetConfigFile(configPath)
    v.SetEnvPrefix("APP")
    v.AutomaticEnv()

    if err := v.ReadInConfig(); err != nil {
        return nil, err
    }

    var cfg Config
    if err := v.Unmarshal(&cfg); err != nil {
        return nil, err
    }

    return &cfg, nil
}
yaml
# configs/config.yaml
server:
  port: 8080
  read_timeout: 30

database:
  host: localhost
  port: 5432
  user: postgres
  password: secret
  dbname: myapp