Golang新手求助 - 应用结构设计问题求指导
Golang新手求助 - 应用结构设计问题求指导 你好
我写Go代码有一段时间了,但还没有完全靠自己从零开始编写过生产级的应用程序。
我写了一个基础结构,包含一些基础代码,需要有人帮我审查一下,看看我做得对不对,以及大家通常是怎么做的。
我把Git链接放在这里
avinash92c/appbase
我的旧版基于Golang的微服务基础代码。通过在GitHub上创建账户,为avinash92c/appbase的开发做出贡献。
更多关于Golang新手求助 - 应用结构设计问题求指导的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang新手求助 - 应用结构设计问题求指导的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
看了你的代码库,整体结构清晰,但有几个地方可以优化。以下是我的具体分析和改进建议:
1. 配置管理优化
当前使用全局变量存储配置,建议改为依赖注入方式:
// config/config.go
type Config struct {
Server ServerConfig
Database DatabaseConfig
Redis RedisConfig
}
func Load() (*Config, error) {
// 从环境变量或配置文件加载
var cfg Config
// ... 加载逻辑
return &cfg, nil
}
2. 数据库层改进
当前直接暴露*sql.DB,建议添加Repository模式:
// internal/repository/user_repository.go
type UserRepository interface {
Create(ctx context.Context, user *User) error
FindByID(ctx context.Context, id int64) (*User, error)
}
type userRepository struct {
db *sql.DB
}
func NewUserRepository(db *sql.DB) UserRepository {
return &userRepository{db: db}
}
3. 服务层添加
建议在handler和repository之间添加服务层:
// internal/service/user_service.go
type UserService struct {
repo repository.UserRepository
// 可以注入其他依赖如logger, cache等
}
func (s *UserService) CreateUser(ctx context.Context, req CreateUserRequest) error {
// 业务逻辑验证
if req.Name == "" {
return errors.New("name is required")
}
// 调用repository
user := &User{Name: req.Name}
return s.repo.Create(ctx, user)
}
4. 依赖注入优化
使用wire或手动依赖注入:
// cmd/api/main.go
func main() {
cfg := config.Load()
db := database.New(cfg.Database)
defer db.Close()
userRepo := repository.NewUserRepository(db)
userService := service.NewUserService(userRepo)
handler := handler.NewUserHandler(userService)
router := chi.NewRouter()
router.Post("/users", handler.CreateUser)
http.ListenAndServe(":8080", router)
}
5. 错误处理改进
定义应用级错误类型:
// internal/errors/app_error.go
type AppError struct {
Code string
Message string
Err error
}
func (e *AppError) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %v", e.Message, e.Err)
}
return e.Message
}
var (
ErrNotFound = &AppError{Code: "NOT_FOUND", Message: "resource not found"}
ErrInvalidInput = &AppError{Code: "INVALID_INPUT", Message: "invalid input"}
)
6. 中间件优化
当前中间件可以更模块化:
// internal/middleware/logging.go
func Logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 使用response writer wrapper记录状态码
rw := &responseWriter{ResponseWriter: w}
next.ServeHTTP(rw, r)
log.Printf("%s %s %d %v",
r.Method,
r.URL.Path,
rw.status,
time.Since(start))
})
}
7. 测试结构
添加测试示例:
// internal/service/user_service_test.go
func TestUserService_CreateUser(t *testing.T) {
mockRepo := &mockUserRepository{}
service := NewUserService(mockRepo)
err := service.CreateUser(context.Background(), CreateUserRequest{
Name: "John Doe",
})
assert.NoError(t, err)
assert.True(t, mockRepo.createCalled)
}
你的基础结构已经不错,主要是需要更清晰的分层和依赖管理。建议参考标准项目布局(Standard Go Project Layout),保持代码的可测试性和可维护性。

