Golang REST API 文件结构这样设计合理吗?
Golang REST API 文件结构这样设计合理吗? 我正在为我的REST API使用这个结构,这样没问题吗?我使用的是gin-gonic。

谢谢,但你觉得我的结构怎么样?
更多关于Golang REST API 文件结构这样设计合理吗?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
非常感谢大家的回复,所有功能都完美运行,非常感谢各位。
虽然没有为Go语言相关的REST API制定结构的具体规则,但你可以采用一些最佳实践来设计端点,例如:

RESTful API设计:最佳实践精要
设计HTTP和RESTful API的最佳实践。介绍URL结构、HTTP方法、关系、分页和版本控制。
关于文件结构,我为每个端点使用一个文件,相应地命名,并加上api前缀以区别于常规文件。
嗯,我对你的项目一无所知,所以我的观点可能非常主观,但我可以提出一些观察,不是因为事情做错了,而是因为从我的角度来看,可以做得更好。
然而,一般来说,如果你有大量的端点,将端点放入包中可能是有用的,否则在主程序和包之间进行数据交换会有点烦人。另外,我不知道你为什么使用一个中间的 lib 文件夹,因为看起来你的项目不是一个库,而更像是一些服务(如果我错了,请跳过阅读这一段 😄)。
根据一些约定,大写字母用于常量或某些方法(例如 GET、PUT 等),而不是包名,所以我会避免使用 ROUTES,而使用 routes。
另一点是在包路径中使用相对路径,这不是一个好的做法(互联网上有很多关于此的解释)。你应该考虑使用绝对路径、GOPATH、vendoring 或 Go 模块。
这个文件结构设计存在几个问题,建议调整如下:
主要问题:
- 控制器直接依赖模型,导致业务逻辑与数据层紧耦合
- 缺少服务层处理业务逻辑
- 路由定义分散在控制器中
改进后的结构示例:
project/
├── cmd/
│ └── api/
│ └── main.go
├── internal/
│ ├── handler/
│ │ ├── user_handler.go
│ │ └── product_handler.go
│ ├── service/
│ │ ├── user_service.go
│ │ └── product_service.go
│ ├── repository/
│ │ ├── user_repository.go
│ │ └── product_repository.go
│ └── model/
│ ├── user.go
│ └── product.go
├── pkg/
│ ├── config/
│ ├── middleware/
│ └── utils/
├── api/
│ └── routes.go
├── go.mod
└── go.sum
示例代码实现:
// internal/handler/user_handler.go
package handler
import (
"net/http"
"yourproject/internal/service"
"github.com/gin-gonic/gin"
)
type UserHandler struct {
userService service.UserService
}
func NewUserHandler(us service.UserService) *UserHandler {
return &UserHandler{userService: us}
}
func (h *UserHandler) GetUser(c *gin.Context) {
id := c.Param("id")
user, err := h.userService.GetUserByID(id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, user)
}
// internal/service/user_service.go
package service
import (
"yourproject/internal/model"
"yourproject/internal/repository"
)
type UserService interface {
GetUserByID(id string) (*model.User, error)
}
type userService struct {
userRepo repository.UserRepository
}
func NewUserService(ur repository.UserRepository) UserService {
return &userService{userRepo: ur}
}
func (s *userService) GetUserByID(id string) (*model.User, error) {
return s.userRepo.FindByID(id)
}
// internal/repository/user_repository.go
package repository
import "yourproject/internal/model"
type UserRepository interface {
FindByID(id string) (*model.User, error)
}
type userRepository struct {
// db connection
}
func NewUserRepository() UserRepository {
return &userRepository{}
}
func (r *userRepository) FindByID(id string) (*model.User, error) {
// database query implementation
return &model.User{ID: id, Name: "John Doe"}, nil
}
// api/routes.go
package api
import (
"yourproject/internal/handler"
"yourproject/internal/repository"
"yourproject/internal/service"
"github.com/gin-gonic/gin"
)
func SetupRouter() *gin.Engine {
r := gin.Default()
// Dependency injection
userRepo := repository.NewUserRepository()
userService := service.NewUserService(userRepo)
userHandler := handler.NewUserHandler(userService)
// Routes
v1 := r.Group("/api/v1")
{
v1.GET("/users/:id", userHandler.GetUser)
}
return r
}
// cmd/api/main.go
package main
import (
"yourproject/api"
)
func main() {
r := api.SetupRouter()
r.Run(":8080")
}
这种分层架构(Handler → Service → Repository)提供了更好的关注点分离、可测试性和可维护性。

