背景知识
为什么要使用Go框架
- 如果不使用框架,在创建服务器和调用端口时会遇到各种各样“奇怪”的问题(就是出错的排查方向可能达到十几种),而且这些问题很难有相似性。
- 同时作为适应于微服务的一门语言,代码的规范化和可读性随着框架的使用,会显著提高。
Gin框架学习配套
- 建议使用
talend api tester
进行路由查询,这样整个http报文的内容很清晰(在chrome浏览器中下载插件即可) - 建议简要学习一下http协议的基础知识,报文,指令,响应码等
- 了解go的基本指令
cd``````run``````build
等,以及文件管理和包的声名 - 建议使用国内的镜像源(毕竟服务器这种,网络情况复杂,最好使用国内的)
环境搭建
- 使用下面的指令(如果编译器自动创建go.mod文件的话,就不用了):
go mod init <项目名称>
- 使用以下指令获取gin包:
go get -u github.com/gin-gonic/gin
- 如果正常的话,有一个
go.mod
文件和一个go.sum
文件,可以简单查看其中有没有内容
路由
首先,常见的http请求有以下四种
- GET(获取)
- POST(上传)
- PUT(局部上传\更新)
- DELETE(删除)
实例
router包->router.go
文件
package router
import (
"github.com/gin-gonic/gin"
"net/http"
)
// 路由 函数的名字要大写,这样才可以被其他包访问!
func Router() *gin.Engine {
//创建一个路由的实例
r := gin.Default()
//实现GET路由 获取
r.GET("/hello", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "hello world")
})
//创建这样一个组,简化代码
user := r.Group("/user")
{
user.POST("/list", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user list")
})
user.PUT("/add", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user update")
})
user.DELETE("/delete", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user delete")
})
}
return r
}
main.go
文件
package main
import "GinLearning/router"
// 入口文件
func main() {
r := router.Router()
r.Run(":9999")
}
Json
的实现
在前后端传输数据的时候,常用的方法就是使用Json
格式,而在Gin框架中,想要创建使用Json
文件传输只需要调用Json
方法
直接实现
这种实现方法容易讲清楚实现的方式和包之间相互调用的原理。但是,由于Go语言管理函数的方式是<包名称>.<函数>
,因此在一个包的不同文件中(可能是针对不同的对象),容易引起函数的重载。因此,可以先通过这个方法简单了解一下实现Json
方法是如何调用的,之后再去看下一种常见的方法。
文件结构:
代码:
mian.go
不变
User.go
package controllers
import "github.com/gin-gonic/gin"
//实现关于用户的功能
func GetUserInfo(c *gin.Context) {
//ReturnSuccess(c *gin.Context, code int, msg interface{}, data interface{}, count int64)
ReturnSuccess(c, 0, "Success", "UserInfo", 1)
}
func GetList(c *gin.Context) {
//ReturnError(c *gin.Context, code int, msg string)
ReturnError(c, 404, "没有相关信息")
}
common.go
package controllers
import (
"github.com/gin-gonic/gin"
"net/http"
)
type JsonStruct struct {
Code int `json:"code"`
Data interface{} `json:"data"`
Msg interface{} `json:"msg"`
Count int64 `json:"count"`
}
type JsonErrStruct struct {
Code int `json:"code"`
Msg interface{} `json:"msg"`
}
func ReturnSuccess(c *gin.Context, code int, msg interface{}, data interface{}, count int64) {
//csde:响应码,msg:泛型信息,data:泛型数据,count:信息条数
json := &JsonStruct{Code: code, Msg: msg, Data: data, Count: count}
c.JSON(http.StatusOK, json)
}
func ReturnError(c *gin.Context, code int, msg string) {
json := &JsonErrStruct{Code: code, Msg: msg}
c.JSON(http.StatusOK, json)
}
router.go
package router
import (
"GinLearning/controllers"
"github.com/gin-gonic/gin"
"net/http"
)
// 路由 函数的名字要大写,这样才可以被其他包访问!
func Router() *gin.Engine {
//创建一个路由的实例
r := gin.Default()
//实现GET路由 获取
r.GET("/hello", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "hello world")
})
//创建这样一个组,简化代码
user := r.Group("/user")
{
user.GET("/info", controllers.GetUserInfo)
user.POST("/list", controllers.GetList)
user.PUT("/add", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user update")
})
user.DELETE("/delete", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user delete")
})
}
return r
}
实现方法:
使用“类+方法”方式实现
只需要使用一个空的类,就可以把相同名称的函数变成不同类的方法
user.go
// 实现关于用户的功能
type UserController struct{}
func (u UserController) GetUserInfo(c *gin.Context) {
//ReturnSuccess(c *gin.Context, code int, msg interface{}, data interface{}, count int64)
ReturnSuccess(c, 0, "Success", "UserInfo", 1)
}
func (u UserController) GetList(c *gin.Context) {
//ReturnError(c *gin.Context, code int, msg string)
ReturnError(c, 404, "没有相关信息User")
}
router.go
分组对不同类进行管理
user := r.Group("/user")
{
user.GET("/info", controllers.UserController{}.GetUserInfo)
user.POST("/list", controllers.UserController{}.GetList)
user.PUT("/add", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user update")
})
user.DELETE("/delete", func(ctx *gin.Context) {
ctx.String(http.StatusOK, "user delete")
})
}
order := r.Group("/order")
{
order.GET("/list", controllers.OrderController{}.GetList)
}
获取信息
使用 /
传入信息
我们在user文件中实现
router.go
user.GET("/info/:id/:name", controllers.UserController{}.GetUserInfo)
user.go
使用Param方法获取
func (u UserController) GetUserInfo(c *gin.Context) {
//ReturnSuccess(c *gin.Context, code int, msg interface{}, data interface{}, count int64)
id := "用户的Id是:" + c.Param("id") + ""
name := "用户的Name是:" + c.Param("name") + ""
ReturnSuccess(c, 0, name, id, 1)
}
使用报文体(body)传入信息
我们在order文件中实现(这种方法的路由部分是不需要改动的)
order.go
package controllers
import "github.com/gin-gonic/gin"
type OrderController struct{}
func (o OrderController) GetList(c *gin.Context) {
cid := c.PostForm("cid")
name := c.DefaultPostForm("name", "未获取输入") //第二个参数是设置为获取输入输出的默认值
ReturnSuccess(c, 0, cid, name, 1)
}
使用Json
格式传入信息
在gooduser
文件中实现
type GoodUserController struct{}
type Search struct {
Cid int `json:"cid"` //前端传过来的小写
Name string `json:"name"`
}
func (p GoodUserController) GetList(c *gin.Context) {
search := Search{}
err := c.BindJSON(&search)
if err != nil {
ReturnError(c, 400, err.Error()) // 返回错误,状态码可以选择 400(Bad Request)
return
}
ReturnSuccess(c, 0, search.Cid, search.Name, 1) // 仅在没有错误时返回成功
}
func (p GoodUserController) GetList2(c *gin.Context) {
param := make(map[string]interface{})
err := c.BindJSON(¶m)
if err != nil {
ReturnError(c, 400, err.Error())
}
ReturnSuccess(c, 0, param, param, 1)
}