社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
上一节 从零开始搭建go项目(gin框架)(一) 中,我们已经实现了一个go项目的基础搭建,实现了程序可访问,本节,我们继续对该项目进行完善和补充。
根目录创建router目录,目录下创建router.go路由文件,同时,创建根目录创建api/v1目录,作为我们的接口目录,可以看做控制层。
package router
import (
"github.com/gin-gonic/gin"
"word-dect-go/api/v1"
)
func Http(router *gin.Engine) {
apiRouter := router.Group("/api/v1/")
{
apiRouter.POST("/detect", v1.Detect)
}
}
路由规则可以参考 grouping-routes , v1是v1版本的意思,之所以这样设置,是因为对外提供的接口,后期经常是有版本迭代的需求的,这样的话,方便以后对外提供多个版本的接口。
修改main.go文件,替换调原来的路由:
修改后的main.go
package main
import (
"github.com/gin-gonic/gin"
"word-dect-go/router"
)
func main() {
// 1.创建路由
r := gin.Default()
// 2.绑定路由规则,执行的函数
// gin.Context,封装了request和response
router.Http(r)
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8088")
r.Run(":8088")
}
根目录创建library文件夹,用于存储一些公共的功能性的包。
首先,我们先定义一下接口返回的错误码,创建文件./library/error_code.go
package library
const (
ErrnoSuccess = 0
ErrnoError = 1
ErrnoUnknown = 2
)
var ErrNoToMsgMap = map[int32]string{
ErrnoSuccess: "success",
ErrnoError: "failed",
ErrnoUnknown: "unknown",
}
func GetErrMsg(errNo int32) string {
if errMsg, ok := ErrNoToMsgMap[errNo]; ok {
return errMsg
}
return "unknown error"
}
其次,创建接口返回体定义以及相关方法,./library/response.go
package library
import (
"encoding/json"
"github.com/gin-gonic/gin"
"net/http"
)
type ResponseBody struct {
Errno int32 `json:"errno"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
func NewResponseBody() *ResponseBody {
return &ResponseBody{
Errno: ErrnoSuccess,
Msg: GetErrMsg(ErrnoSuccess),
Data: map[string]interface{}{},
}
}
func (res *ResponseBody) SetData(data interface{}) {
res.Data = data
}
func (res *ResponseBody) SetErrNo(errNo int32) {
res.Errno = errNo
}
func (res *ResponseBody) SetErrMsg(errMsg string) {
res.Msg = errMsg
}
func RecoverResponse(ctx *gin.Context, responseBody *ResponseBody) {
// panic
if err := recover(); err != nil {
responseBody.SetErrNo(ErrnoUnknown)
}
resp, err := json.Marshal(responseBody)
if err != nil {
ctx.Data(http.StatusOK, "application/json;charset=utf-8", []byte(`{"errno":1,"msg":"unknown"}`))
} else {
ctx.Data(http.StatusOK, "application/json;charset=utf-8", resp)
}
return
}
根目录创建service目录,实际处理接口内部逻辑,可以看做业务层或模型层
接下来,我们来具体实现router路由里定义的接口 /api/v1/detect的业务逻辑
创建文件 ./service/detect.go
package service
import (
"github.com/gin-gonic/gin"
"word-dect-go/library"
)
// 请求参数结构体
type DetectRequestParams struct {
Text string `json:"text"`
Ctx *gin.Context
}
func Detect(param *DetectRequestParams, responseBody *library.ResponseBody) {
responseBody.SetData(param.Text)
return
}
创建文件 ./api/v1/detect.go,承接路由中配置的接口/api/v1/detect 对应的 v1.Detect()方法,内部调用service.Detect()来实现接口具体的业务处理
package v1
import (
"github.com/gin-gonic/gin"
"word-dect-go/library"
"word-dect-go/service"
)
func Detect(ctx *gin.Context) {
responseBody := library.NewResponseBody()
defer library.RecoverResponse(ctx, responseBody)
param := &service.DetectRequestParams{Ctx: ctx}
ctx.BindJSON(param)
service.Detect(param, responseBody)
}
因为我们路由中,该接口定义的是只接受POST请求,所以只能post方式才可以请求通接口
如果想要接受GET请求的话,只需将POST改为GET即可,或者改为Any, 则可同时接受get和post请求
至此,一个简单的接口,我们就已经实现了。
本节中,我们首先是实现了路由控制,以及基础的接口返回以及错误码这几个框架层面上的基础功能模块。这些模块抽象出来后,可以极大的简化我们日后的具体的业务逻辑开发,使得开发时无需再去关心这些。
其次,大家应该也注意到,在api/v1/detect.go中,接受参数时,我们是通过一个参数结构体来接收的:
param := &service.DetectRequestParams{Ctx: ctx}
ctx.BindJSON(param)
// 请求参数结构体
type DetectRequestParams struct {
Text string `json:"text"`
Ctx *gin.Context
}
这样的做法,一方面是规范了我们的接口参数的字段与类型,另一方面也起到了接口参数检查的作用,同时如果后续调用该参数,可以直接调用,更加的方便。
https://github.com/gin-gonic/gin
推荐: 浮生无事Blog
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!