基于 gin框架搭建入门项目

go mod init gin-ranking
go: creating new go.mod: module gin-ranking
go: to add module requirements and sums:
        go mod tidy

下载gin框架

cmd窗口中执行命令:

go get -u github.com/gin-gonic/gin
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	r.GET("/hello", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "hello world!")
	})

	r.POST("/user/list", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "user list!")
	})

	r.PUT("/user/add", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "user add !")
	})

	r.DELETE("/user/delete", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "user delete!")
	})

	r.Run(":9999")
}

运行

go run main.go

在这里插入图片描述

也可以支持分组

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	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 add !")
		})

		user.DELETE("/delete", func(ctx *gin.Context) {
			ctx.String(http.StatusOK, "user delete!")
		})

	}

	r.Run(":9999")
}

如果路由有很多个都放在main.go文件中不太好

在这里插入图片描述

封装Json 返回统一格式

在这里插入图片描述

main.go

package main

import "gin-ranking/router"

func main() {
	r := router.Router()
	r.Run(":9999")
}

router.go

package router

import (
	"gin-ranking/controllers"
	"github.com/gin-gonic/gin"
	"net/http"
)

func Router() *gin.Engine {
	r := gin.Default()

	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 add !")
		})

		user.DELETE("/delete", func(ctx *gin.Context) {
			ctx.String(http.StatusOK, "user delete!")
		})

	}
	return r

}

user.go

package controllers

import "github.com/gin-gonic/gin"

func GetUserInfo(c *gin.Context) {
	ReturnSuccess(c, 0, "success", "user info", 1)
}

func GetList(c *gin.Context) {
	ReturnError(c, 404, "没有相关信息")
}

common.go

package controllers

import "github.com/gin-gonic/gin"

type JsonStruct struct {
	Code  int         `json:"code"`
	Msg   interface{} `json:"msg"`
	Data  interface{} `json:"data"`
	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) {
	json := &JsonStruct{
		Code: code, Msg: msg, Data: data, Count: count,
	}
	c.JSON(200, json)
}

func ReturnError(c *gin.Context, code int, msg interface{}) {
	json := &JsonErrStruct{Code: code, Msg: msg}
	c.JSON(200, json)
}

127.0.0.1:9999/user/info
{
    "code": 0,
    "msg": "success",
    "data": "user info",
    "count": 1
}
127.0.0.1:9999/user/list

{
    "code": 404,
    "msg": "没有相关信息"
}

在这里插入图片描述

但是有个问题,如果在别的包中调用同一个方法就会报错,可以借用结构体

router.go

package router

import (
	"gin-ranking/controllers"
	"github.com/gin-gonic/gin"
	"net/http"
)

func Router() *gin.Engine {
	r := gin.Default()

	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 add !")
		})

		user.DELETE("/delete", func(ctx *gin.Context) {
			ctx.String(http.StatusOK, "user delete!")
		})

	}

	order := r.Group("/order")
	{
		order.POST("/list", controllers.OrderController{}.GetList)
	}
	return r

}

order.go

package controllers

import "github.com/gin-gonic/gin"

type OrderController struct {
}

func (o OrderController) GetList(c *gin.Context) {
	ReturnError(c, 404, "没有相关信息 order")
}

user.go

package controllers

import "github.com/gin-gonic/gin"

type UserController struct {
}

func (u UserController) GetUserInfo(c *gin.Context) {
	ReturnSuccess(c, 0, "success", "user info", 1)
}

func (u UserController) GetList(c *gin.Context) {
	ReturnError(c, 404, "没有相关信息")
}

获取请求参数并和struct结构体绑定

1.get 请求 携带路由参数
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Post传递表单类型的参数
在这里插入图片描述
在这里插入图片描述

传递json类型的数据
在这里插入图片描述
通过定义结构体的方式传递
在这里插入图片描述

自定义Logger中间件实现日志收集

根目录下新建 runtime/log 目录用以保存生成的日志

根目录下新建pkg/logger/logger.go

package logger

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"io"
	"net/http"
	"os"
	"path"
	"runtime/debug"
	"time"
)

func init() {
	// 设置日志格式为json格式
	logrus.SetFormatter(&logrus.JSONFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	})
	logrus.SetReportCaller(false)
}

func Write(msg string, filename string) {
	setOutPutFile(logrus.InfoLevel, filename)
	logrus.Info(msg)
}

func Debug(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.DebugLevel, "debug")
	logrus.WithFields(fields).Debug(args)
}

func Info(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.InfoLevel, "info")
	logrus.WithFields(fields).Info(args)
}

func Warn(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.WarnLevel, "warn")
	logrus.WithFields(fields).Warn(args)
}

func Fatal(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.FatalLevel, "fatal")
	logrus.WithFields(fields).Fatal(args)
}

func Error(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.ErrorLevel, "error")
	logrus.WithFields(fields).Error(args)
}

func Panic(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.PanicLevel, "panic")
	logrus.WithFields(fields).Panic(args)
}

func Trace(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.TraceLevel, "trace")
	logrus.WithFields(fields).Trace(args)
}

func setOutPutFile(level logrus.Level, logName string) {
	if _, err := os.Stat("./runtime/log"); os.IsNotExist(err) {
		err = os.MkdirAll("./runtime/log", 0777)
		if err != nil {
			panic(fmt.Errorf("create log dir '%s' error: %s", "./runtime/log", err))
		}
	}

	timeStr := time.Now().Format("2006-01-02")
	fileName := path.Join("./runtime/log", logName+"_"+timeStr+".log")

	var err error
	os.Stderr, err = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("open log file err", err)
	}
	logrus.SetOutput(os.Stderr)
	logrus.SetLevel(level)
	return
}

func LoggerToFile() gin.LoggerConfig {

	if _, err := os.Stat("./runtime/log"); os.IsNotExist(err) {
		err = os.MkdirAll("./runtime/log", 0777)
		if err != nil {
			panic(fmt.Errorf("create log dir '%s' error: %s", "./runtime/log", err))
		}
	}

	timeStr := time.Now().Format("2006-01-02")
	fileName := path.Join("./runtime/log", "success_"+timeStr+".log")

	os.Stderr, _ = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)

	var conf = gin.LoggerConfig{
		Formatter: func(param gin.LogFormatterParams) string {
			return fmt.Sprintf("%s - %s \"%s %s %s %d %s \"%s\" %s\"\n",
				param.TimeStamp.Format("2006-01-02 15:04:05"),
				param.ClientIP,
				param.Method,
				param.Path,
				param.Request.Proto,
				param.StatusCode,
				param.Latency,
				param.Request.UserAgent(),
				param.ErrorMessage,
			)
		},
		Output: io.MultiWriter(os.Stdout, os.Stderr),
	}

	return conf
}

func Recover(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			if _, errDir := os.Stat("./runtime/log"); os.IsNotExist(errDir) {
				errDir = os.MkdirAll("./runtime/log", 0777)
				if errDir != nil {
					panic(fmt.Errorf("create log dir '%s' error: %s", "./runtime/log", errDir))
				}
			}

			timeStr := time.Now().Format("2006-01-02")
			fileName := path.Join("./runtime/log", "error_"+timeStr+".log")

			f, errFile := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
			if errFile != nil {
				fmt.Println(errFile)
			}
			timeFileStr := time.Now().Format("2006-01-02 15:04:05")
			f.WriteString("panic error time:" + timeFileStr + "\n")
			f.WriteString(fmt.Sprintf("%v", err) + "\n")
			f.WriteString("stacktrace from panic:" + string(debug.Stack()) + "\n")
			f.Close()
			c.JSON(http.StatusOK, gin.H{
				"code": 500,
				"msg":  fmt.Sprintf("%v", err),
			})
			//终止后续接口调用,不加的话recover到异常后,还会继续执行接口里后续代码
			c.Abort()
		}
	}()
	c.Next()
}

直接在方法中调用
在这里插入图片描述
在这里插入图片描述

引入Gorm

根目录新建config/db.go
在这里插入图片描述
根目录新建dao/dao.go
在这里插入图片描述

package dao

import (
	"gin-ranking/config"
	"gin-ranking/pkg/logger"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"time"
)

var (
	Db  *gorm.DB
	err error
)

func init() {
	Db, err = gorm.Open("mysql", config.Mysqldb)
	if err != nil {
		logger.Error(map[string]interface{}{"mysql connect error": err.Error()})
	}
	if Db.Error != nil {
		logger.Error(map[string]interface{}{"database error": Db.Error})
	}

	// ----------------------- 连接池设置 -----------------------
	// SetMaxIdleConns 设置空闲连接池中连接的最大数量
	Db.DB().SetMaxIdleConns(10)

	// SetMaxOpenConns 设置打开数据库连接的最大数量。
	Db.DB().SetMaxOpenConns(100)

	// SetConnMaxLifetime 设置了连接可复用的最大时间。
	Db.DB().SetConnMaxLifetime(time.Hour)
}

新建models/user 测试
在这里插入图片描述
在请求方法中直接调用
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

新增用户
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

更新数据
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

删除
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

查询多条数据
models

func GerUserListTest() ([]User, error) {
	var users []User
	err := dao.Db.Where("id<?", 3).Find(&users).Error
	return users, err
}

controllers

func (u UserController) GerUserListTest(c *gin.Context) {
	users, err := models.GerUserListTest()
	if err != nil {
		ReturnError(c, 4004, "删除失败")
		return
	}
	ReturnSuccess(c, 0, "删除成功", users, 1)

}

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
好的,让我们来讲一下如何使用Gin框架进行项目实战。 首先,我们需要安装Gin框架。可以使用以下命令进行安装: ``` go get -u github.com/gin-gonic/gin ``` 接下来,我们可以创建一个简单的web服务。在这个例子中,我们将创建一个API,用于获取用户信息。我们将使用以下代码: ```go package main import ( "net/http" "github.com/gin-gonic/gin" ) type User struct { Name string `json:"name"` Email string `json:"email"` } func main() { router := gin.Default() router.GET("/users/:id", func(c *gin.Context) { id := c.Param("id") user := User{ Name: "John Doe", Email: "[email protected]", } c.JSON(http.StatusOK, gin.H{ "id": id, "user": user, }) }) router.Run(":8080") } ``` 在这个例子中,我们定义了一个User结构体和一个处理路由的函数。当我们访问/users/:id路由时,会返回一个JSON格式的响应,包含用户的信息。 接下来,我们可以使用PostgreSQL数据库来存储和检索用户信息。我们可以使用以下代码连接到PostgreSQL: ```go package main import ( "database/sql" "log" "net/http" "github.com/gin-gonic/gin" _ "github.com/lib/pq" ) type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` } func main() { db, err := sql.Open("postgres", "user=postgres password=postgres dbname=postgres sslmode=disable") if err != nil { log.Fatalln(err) } router := gin.Default() router.GET("/users/:id", func(c *gin.Context) { id := c.Param("id") var user User err := db.QueryRow("SELECT id, name, email FROM users WHERE id = $1", id).Scan(&user.ID, &user.Name, &user.Email) if err != nil { log.Println(err) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal server error", }) return } c.JSON(http.StatusOK, gin.H{ "id": id, "user": user, }) }) router.Run(":8080") } ``` 在这个例子中,我们在路由处理函数中查询了一个名为users的表,该表包含用户的信息。我们使用`github.com/lib/pq`库来连接到PostgreSQL数据库。 以上就是使用Gin框架进行项目实战的基本流程。当然,具体的项目实战过程中,需要根据具体需求进行更加详细的开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季布,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值