golang结构化开发Web应用服务的规范指南插件goapp的使用
Golang结构化开发Web应用服务的规范指南插件goapp的使用
Goapp v1.0
这是一个基于9年以上Go Web应用/服务开发经验形成的结构化开发指南,结合了领域驱动设计(DDD)和清洁架构(Clean Architecture)的理念。适用于Go 1.4+版本(引入了特殊的’internal’目录)。
目录结构
├── cmd
│ ├── server
│ │ ├── grpc
│ │ │ └── grpc.go
│ │ └── http
│ │ ├── handlers.go
│ │ ├── handlers_usernotes.go
│ │ ├── handlers_users.go
│ │ ├── http.go
│ │ └── web
│ │ └── templates
│ │ └── index.html
│ └── subscribers
│ └── kafka
│ └── kafka.go
├── docker
│ ├── docker-compose.yml
│ └── Dockerfile
├── go.mod
├── go.sum
├── internal
│ ├── api
│ │ ├── api.go
│ │ ├── usernotes.go
│ │ └── users.go
│ ├── configs
│ │ └── configs.go
│ ├── pkg
│ │ ├── apm
│ │ │ ├── apm.go
│ │ │ ├── grpc.go
│ │ │ ├── http.go
│ │ │ ├── meter.go
│ │ │ ├── prometheus.go
│ │ │ └── tracer.go
│ │ ├── logger
│ │ │ ├── default.go
│ │ │ └── logger.go
│ │ ├── postgres
│ │ │ └── postgres.go
│ │ └── sysignals
│ │ └── sysignals.go
│ ├── usernotes
│ │ ├── store_postgres.go
│ │ └── usernotes.go
│ └── users
│ ├── store_postgres.go
│ └── users.go
├── lib
│ └── goapp
│ ├── goapp.go
│ ├── go.mod
│ └── go.sum
├── LICENSE
├── main.go
├── inits.go
├── shutdown.go
├── README.md
└── schemas
├── functions.sql
├── user_notes.sql
└── users.sql
主要组件说明
internal/configs
配置包,集中管理应用配置,便于后续从环境变量或配置中心读取配置。
// configs.go 示例
package configs
type HTTP struct {
Host string
Port int
}
func HTTPConfig() *HTTP {
return &HTTP{
Host: "0.0.0.0",
Port: 8080,
}
}
internal/api
API包集中管理所有对外暴露的API,确保不同I/O方式(HTTP/gRPC等)行为一致。
// api.go 示例
package api
import (
"context"
"github.com/naughtygopher/goapp/internal/users"
)
type API struct {
users *users.Users
}
func New(users *users.Users) *API {
return &API{
users: users,
}
}
func (a *API) CreateUser(ctx context.Context, name, email string) error {
return a.users.Create(ctx, name, email)
}
internal/users
用户业务逻辑包,包含用户相关的核心业务逻辑。
// users.go 示例
package users
import (
"context"
"strings"
)
type Store interface {
Create(ctx context.Context, name, email string) error
Get(ctx context.Context, email string) (string, error)
}
type Users struct {
store Store
}
func New(store Store) *Users {
return &Users{
store: store,
}
}
func (u *Users) Create(ctx context.Context, name, email string) error {
name = strings.TrimSpace(name)
email = strings.TrimSpace(email)
// 业务验证逻辑
if name == "" {
return errors.New("name cannot be empty")
}
return u.store.Create(ctx, name, email)
}
internal/pkg/postgres
PostgreSQL工具包,初始化数据库连接池并返回实例。
// postgres.go 示例
package postgres
import (
"context"
"github.com/jackc/pgx/v4/pgxpool"
)
func New(ctx context.Context, connString string) (*pgxpool.Pool, error) {
config, err := pgxpool.ParseConfig(connString)
if err != nil {
return nil, err
}
return pgxpool.ConnectConfig(ctx, config)
}
完整示例Demo
// main.go 示例
package main
import (
"context"
"log"
"github.com/naughtygopher/goapp/internal/api"
"github.com/naughtygopher/goapp/internal/configs"
"github.com/naughtygopher/goapp/internal/pkg/postgres"
"github.com/naughtygopher/goapp/internal/users"
"github.com/naughtygopher/goapp/cmd/server/http"
)
func main() {
ctx := context.Background()
// 初始化配置
cfg := configs.HTTPConfig()
// 初始化数据库
db, err := postgres.New(ctx, "postgres://user:pass@localhost:5432/db")
if err != nil {
log.Fatal(err)
}
// 初始化用户服务
userStore := users.NewPostgresStore(db)
userService := users.New(userStore)
// 初始化API
appAPI := api.New(userService)
// 启动HTTP服务器
srv := http.New(cfg, appAPI)
if err := srv.Start(); err != nil {
log.Fatal(err)
}
}
运行应用
$ git clone https://github.com/naughtygopher/goapp.git
$ cd goapp
# 更新internal/configs/configs.go中的数据库配置
$ TEMPLATES_BASEPATH=${PWD}/cmd/server/http/web/templates go run main.go | sed 's/\\n/\n/g;s/\\t/\t/g'
使用goapp创建新项目
$ gonew github.com/naughtygopher/goapp@latest my.app
$ cd my.app
关键设计理念
- 依赖注入:通过接口实现依赖反转,便于测试和维护
- 分层架构:清晰的业务逻辑、数据访问和API分层
- 错误处理:使用自定义错误包统一处理错误和日志
- 可观测性:集成OpenTelemetry进行应用性能监控
示例截图
更多关于golang结构化开发Web应用服务的规范指南插件goapp的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang结构化开发Web应用服务的规范指南插件goapp的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 结构化 Web 应用开发规范与 goapp 插件使用指南
1. 结构化 Web 应用开发规范
1.1 项目目录结构
推荐的标准项目结构:
/myapp
├── cmd/ # 主应用程序入口
│ └── myapp/ # 主程序目录
│ └── main.go # 主程序入口
├── internal/ # 私有应用程序代码
│ ├── config/ # 配置处理
│ ├── controllers/ # 控制器层
│ ├── models/ # 数据模型层
│ ├── services/ # 业务逻辑层
│ ├── repositories/ # 数据访问层
│ └── middleware/ # 中间件
├── pkg/ # 可公开的库代码
├── api/ # API 定义文件(Swagger/Protobuf等)
├── web/ # Web 资源(模板/静态文件)
├── scripts/ # 脚本文件
├── configs/ # 配置文件
├── tests/ # 测试代码
├── go.mod # Go模块定义
└── go.sum # 依赖校验
1.2 分层架构示例代码
// internal/models/user.go
package models
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Username string `json:"username" gorm:"unique"`
Email string `json:"email" gorm:"unique"`
}
// internal/repositories/user_repository.go
package repositories
import "myapp/internal/models"
type UserRepository interface {
Create(user *models.User) error
FindByID(id uint) (*models.User, error)
}
type userRepository struct {
db *gorm.DB
}
func NewUserRepository(db *gorm.DB) UserRepository {
return &userRepository{db: db}
}
func (r *userRepository) Create(user *models.User) error {
return r.db.Create(user).Error
}
// internal/services/user_service.go
package services
import (
"myapp/internal/models"
"myapp/internal/repositories"
)
type UserService interface {
Register(user *models.User) error
GetUser(id uint) (*models.User, error)
}
type userService struct {
userRepo repositories.UserRepository
}
func NewUserService(userRepo repositories.UserRepository) UserService {
return &userService{userRepo: userRepo}
}
func (s *userService) Register(user *models.User) error {
// 业务逻辑处理
return s.userRepo.Create(user)
}
// internal/controllers/user_controller.go
package controllers
import (
"net/http"
"myapp/internal/models"
"myapp/internal/services"
)
type UserController struct {
userService services.UserService
}
func NewUserController(userService services.UserService) *UserController {
return &UserController{userService: userService}
}
func (c *UserController) Register(w http.ResponseWriter, r *http.Request) {
var user models.User
// 解析请求体...
if err := c.userService.Register(&user); err != nil {
// 错误处理
return
}
// 成功响应
}
1.3 路由组织规范
// cmd/myapp/main.go
package main
import (
"myapp/internal/controllers"
"myapp/internal/middleware"
"myapp/internal/services"
"myapp/internal/repositories"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func setupRouter(db *gorm.DB) *gin.Engine {
r := gin.Default()
// 中间件
r.Use(middleware.Logger())
r.Use(middleware.Recovery())
// 初始化各层
userRepo := repositories.NewUserRepository(db)
userService := services.NewUserService(userRepo)
userController := controllers.NewUserController(userService)
// 路由分组
api := r.Group("/api")
{
v1 := api.Group("/v1")
{
user := v1.Group("/users")
{
user.POST("/register", userController.Register)
user.GET("/:id", userController.GetUser)
}
}
}
return r
}
2. goapp 插件使用指南
goapp 是一个帮助快速构建 Go Web 应用的插件/工具集,提供项目脚手架和常用功能集成。
2.1 安装 goapp
go install github.com/goapphub/goapp@latest
2.2 创建新项目
goapp new myapp --module github.com/yourname/myapp
2.3 项目结构生成
goapp 会生成符合最佳实践的项目结构:
/myapp
├── cmd
├── internal
│ ├── config
│ ├── controllers
│ ├── models
│ ├── repositories
│ ├── services
│ └── middleware
├── pkg
├── api
├── web
├── scripts
├── configs
├── tests
├── Dockerfile
├── Makefile
├── go.mod
└── go.sum
2.4 常用命令
# 添加新的API端点
goapp add api users -m get,post,put,delete
# 生成数据库模型
goapp generate model User username:string email:string
# 添加中间件
goapp add middleware JwtAuth
# 运行开发服务器
goapp run
# 构建生产版本
goapp build
2.5 集成功能示例
// 使用goapp的配置加载功能
import "github.com/goapphub/pkg/config"
func main() {
// 加载配置
cfg, err := config.Load("configs/app.yaml")
if err != nil {
panic(err)
}
// 初始化数据库
db, err := initDB(cfg.Database)
if err != nil {
panic(err)
}
// 设置路由
r := setupRouter(db)
// 启动服务器
r.Run(cfg.Server.Address)
}
3. 最佳实践建议
- 依赖注入:使用接口和构造函数进行依赖管理
- 错误处理:统一错误处理中间件
- 日志记录:结构化日志(JSON格式)
- 配置管理:环境变量和配置文件结合
- API文档:集成Swagger/OpenAPI
- 测试:分层测试(单元测试、集成测试)
- 部署:使用Docker容器化
通过遵循这些规范和利用goapp工具,可以快速构建结构清晰、易于维护的Go Web应用程序。