通过使用gin框架写一个获取详情接口,熟悉了以下N个内容
一、框架结构设计
www WEB部署目录(或者子目录)
├─build 应用目录
│ ├─config.yaml 配置文件
│ └─main.go 入口文件
│
├─config 配置目录
│ └─conf.go 配置处理结构体和相关处理函数
│
├─constant 常量目录
│ └─app.go 常量配置文件
│
├─dao 数据访问处理对象(data access object)目录
│ ├─model 数据库表模型目录,每个表在该目录下有一个同名的模型文件
│ | └─table_name.go 表模型文件
| |
│ ├─dao.go 数据访问处理对象基础结构体,包含公共处理方法等
│ ├─bussiness.go 针对“企业表”建立的结构体,包含对企业的各种增删改查操作
│ └─db.go 数据库结构体文件
│
├─http http服务目录
│ ├─request 请求目录,存放各种请求的结构体文件
| | └─xxx.go
│ ├─response 响应目录,存放http请求响应的结构体文件
| | └─xxx.go
│ └─http.go 处理路由初始化等操作
│
├─service 服务目录
| ├─... 更多具体的服务结构体
| └─service.go 基础服务结构体,包含通用的操作和方法
|
└─go.mod go模块依赖配置文件
二、 如何使用ORM查询数据库:
当前我选择了使用gorm来进行数据库操作,查询文档见官方文档,其中数据库表结构体的生成选用了gentool工具。
1. 按指定表名生成结构体文件:
#安装gentool
$go install gorm.io/gen/tools/gentool@latest
#生成结构体
$gentool -dsn "db_account_name:db_password@tcp(数据库ip:端口号)/数据库名称?charset=utf8mb4&parseTime=True&loc=Local&timeout=5s&readTimeout=10s&writeTimeout=5s" -tables "表名列表,逗号分隔"
2. 构建数据库操作对象
#数据库结构体 - dao/db.go
type DbConfig struct {
Server string `yaml:"server" json:"server"`
Port int `yaml:"port" json:"port"`
Database string `yaml:"database" json:"database"`
...
}
#数据库操作对象基础对象dao/dao.go
var Dao = &Instance{}
type Instance struct {
DBMaster *gorm.DB
}
...
#数据库表的结构体 - dao/model/api_system_config.gen.go
...
type APISystemConfig struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
SystemType int32 `gorm:"column:system_type;not null;comment:系统类型:1--YAPI 2--自定义" json:"system_type"` // 系统类型:1--YAPI 2--自定义
Config string `gorm:"column:config;not null;comment:yapi系统自定义配置信息" json:"config"` // yapi系统自定义配置信息
Token string `gorm:"column:token;not null;comment:身份验证token" json:"token"` // 身份验证token
ProjectID int32 `gorm:"column:project_id;not null;comment:所属项目id" json:"project_id"` // 所属项目id
CreateTime time.Time `gorm:"column:create_time;not null;default:1970-01-01 00:00:00;comment:创建时间" json:"create_time"` // 创建时间
UpdateTime time.Time `gorm:"column:update_time;not null;default:1970-01-01 00:00:00;comment:更新时间" json:"update_time"` // 更新时间
Domain string `gorm:"column:domain;comment:域名" json:"domain"` // 域名
}
...
#数据库操作对象 dao/api_system_config.go
...
//定义接口
type ApiSystemConfigInterface interface {
//获取配置详情
GetDetail(ctx context.Context, id int, projectId int) (*response.ApiSystemConfigDetail, error)
}
/**
* api系统配置
*/
type ApiSystemConfig struct {
ins *Instance
}
func NewApiSystemConfig(ins *Instance) ApiSystemConfigInterface {
return &ApiSystemConfig{
ins: ins,
}
}
func (c *ApiSystemConfig) GetDetail(ctx context.Context, id int, projectId int) (*response.ApiSystemConfigDetail, error) {
hand := c.ins.DBMaster.Model(&model.APISystemConfig{})
if id > 0 {
hand.Where("id=?", id)
}
if projectId > 0 {
hand.Where("project_id", projectId)
}
apiCfg := model.APISystemConfig{}
hand.First(&apiCfg)
rspCfg := response.ApiSystemConfigDetail{}
s, err := json.Marshal(apiCfg)
if err != nil {
}
json.Unmarshal(s, &rspCfg)
return &rspCfg, nil
}
三、配置路由和输出格式
在http/http.go中定义路由路由并绑定处理函数,处理函数的定义可以存入按具体业务命名go文件中。
#路由定义 http/http.go
package http
import (
"github.com/gin-gonic/gin"
"visual_api_gin/service"
)
type Controller struct {
srv *service.Service
}
func Init(instance *gin.Engine, srv *service.Service) {
ctrl := &Controller{
srv: srv,
}
initRouter(instance, ctrl)
}
func initRouter(e *gin.Engine, controller *Controller) {
//定义跟目录
g := e.RouterGroup.Group("/v1/services/")
//这里引入中间件
g.Use()
//定义业务分组目录
yapi := g.Group("/project/")
//定义具体接口路由
yapi.GET("/list", controller.Hellow) //获取列表
}
#处理函数定义 http/project.go
package http
import (
"github.com/gin-gonic/gin"
"visual_api_gin/http/response"
)
func (ctrl *Controller) Hellow(ctx *gin.Context) {
a, _ := ctrl.srv.ApiCfg.GetDetail(ctx, 1, 0)
ctx.JSON(200, response.Resp{Code: 200, Data: a})
}
输出一般包含响应码、提示信息和数据三部分。data定义为interace类型是因为每个接口响应的内容都是各自定制化的。
type Resp struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}