Golang项目组织架构的最佳实践有哪些

Golang项目组织架构的最佳实践有哪些 我正在开发一个多CRUD项目。我的项目包含主页、产品页面和客户页面。 但我不知道如何组织项目结构。 目前我把所有代码都写在一个main.go文件里。 所有的.tmpl文件都放在tmpl目录中。 我应该如何组织这个项目? 我的源代码链接。

project.zip

project.zip

请帮帮我。


更多关于Golang项目组织架构的最佳实践有哪些的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang项目组织架构的最佳实践有哪些的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


对于多CRUD项目的组织架构,建议采用分层架构模式。以下是基于你项目需求的最佳实践:

项目结构示例

project/
├── cmd/
│   └── web/
│       └── main.go          # 应用入口
├── internal/
│   ├── handlers/           # HTTP处理器
│   │   ├── home.go
│   │   ├── product.go
│   │   └── customer.go
│   ├── models/             # 数据模型
│   │   ├── product.go
│   │   └── customer.go
│   ├── services/           # 业务逻辑层
│   │   ├── product_service.go
│   │   └── customer_service.go
│   └── repositories/       # 数据访问层
│       ├── product_repo.go
│       └── customer_repo.go
├── pkg/
│   └── utils/              # 可复用工具函数
├── web/
│   ├── templates/          # 模板文件
│   │   ├── base.tmpl
│   │   ├── home/
│   │   ├── products/
│   │   └── customers/
│   └── static/             # 静态文件
├── configs/                # 配置文件
├── migrations/             # 数据库迁移
├── go.mod
└── go.sum

代码示例

1. 主入口文件 (cmd/web/main.go)

package main

import (
    "log"
    "net/http"
    
    "yourproject/internal/handlers"
    "yourproject/internal/config"
)

func main() {
    cfg := config.Load()
    
    // 设置路由
    mux := http.NewServeMux()
    
    // 注册处理器
    homeHandler := handlers.NewHomeHandler()
    productHandler := handlers.NewProductHandler()
    customerHandler := handlers.NewCustomerHandler()
    
    mux.HandleFunc("/", homeHandler.Index)
    mux.HandleFunc("/products", productHandler.Index)
    mux.HandleFunc("/products/create", productHandler.Create)
    mux.HandleFunc("/customers", customerHandler.Index)
    mux.HandleFunc("/customers/create", customerHandler.Create)
    
    log.Printf("Server starting on %s", cfg.ServerAddress)
    log.Fatal(http.ListenAndServe(cfg.ServerAddress, mux))
}

2. 处理器示例 (internal/handlers/product.go)

package handlers

import (
    "html/template"
    "net/http"
    
    "yourproject/internal/models"
    "yourproject/internal/services"
)

type ProductHandler struct {
    productService *services.ProductService
    templates      *template.Template
}

func NewProductHandler() *ProductHandler {
    templates := template.Must(template.ParseGlob("web/templates/products/*.tmpl"))
    return &ProductHandler{
        productService: services.NewProductService(),
        templates:      templates,
    }
}

func (h *ProductHandler) Index(w http.ResponseWriter, r *http.Request) {
    products, err := h.productService.GetAllProducts()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    data := struct {
        Title    string
        Products []models.Product
    }{
        Title:    "Products",
        Products: products,
    }
    
    h.templates.ExecuteTemplate(w, "index.tmpl", data)
}

func (h *ProductHandler) Create(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodPost {
        product := models.Product{
            Name:  r.FormValue("name"),
            Price: r.FormValue("price"),
        }
        
        err := h.productService.CreateProduct(product)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        
        http.Redirect(w, r, "/products", http.StatusSeeOther)
        return
    }
    
    h.templates.ExecuteTemplate(w, "create.tmpl", nil)
}

3. 服务层示例 (internal/services/product_service.go)

package services

import (
    "yourproject/internal/models"
    "yourproject/internal/repositories"
)

type ProductService struct {
    repo *repositories.ProductRepository
}

func NewProductService() *ProductService {
    return &ProductService{
        repo: repositories.NewProductRepository(),
    }
}

func (s *ProductService) GetAllProducts() ([]models.Product, error) {
    return s.repo.FindAll()
}

func (s *ProductService) CreateProduct(product models.Product) error {
    return s.repo.Create(product)
}

func (s *ProductService) GetProductByID(id string) (*models.Product, error) {
    return s.repo.FindByID(id)
}

4. 数据模型示例 (internal/models/product.go)

package models

type Product struct {
    ID    string `json:"id" db:"id"`
    Name  string `json:"name" db:"name"`
    Price string `json:"price" db:"price"`
}

type Customer struct {
    ID        string `json:"id" db:"id"`
    FirstName string `json:"first_name" db:"first_name"`
    LastName  string `json:"last_name" db:"last_name"`
    Email     string `json:"email" db:"email"`
}

5. 模板组织示例 (web/templates/products/index.tmpl)

{{define "title"}}Products{{end}}

{{define "content"}}
<h1>Product List</h1>
<a href="/products/create">Add New Product</a>

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Price</th>
        </tr>
    </thead>
    <tbody>
        {{range .Products}}
        <tr>
            <td>{{.ID}}</td>
            <td>{{.Name}}</td>
            <td>{{.Price}}</td>
        </tr>
        {{end}}
    </tbody>
</table>
{{end}}

这种分层架构提供了清晰的关注点分离,使代码更易于维护、测试和扩展。每个层都有明确的职责:处理器处理HTTP请求,服务层包含业务逻辑,存储库处理数据访问,模型定义数据结构。

回到顶部