gin框架实践连载三 | 自定义目录结构

7,189 阅读3分钟

引言

  • 下载安装gin,并按照demo运行
  • 自定义项目结构
  • 封装config层,定义配置文件
  • github代码地址

1、提取路由

在routes目录下新建route.go

package routes

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"

	"go-api/config"
)

//init router
func InitRouter() *gin.Engine{
    r := initGin()
	loadRoute(r)
	return r;
}

// init Gin
func initGin() *gin.Engine{
	//设置gin模式
	gin.SetMode(config.RunMode)
    return gin.Default()
}

// 加载路由
func loadRoute(r *gin.Engine){
	testRoute(r)
	apiRoute(r)
}

//启动服务器
func Run(){
	r := InitRouter()
	s := &http.Server{
		Addr:           fmt.Sprintf("%s:%d",config.ServerSetting.HttpAddress,config.ServerSetting.HttpPort),
		Handler:        r,
		ReadTimeout:    config.ServerSetting.ReadTimeout,//请求响应的超市时间
		WriteTimeout:   config.ServerSetting.WriteTimeout,//返回响应的超时时间
		//MaxHeaderBytes: 1 << 20,//默认的1MB
	}
	s.ListenAndServe()
}

在routes下新建test.go

package routes

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

func testRoute(r *gin.Engine){
	r.GET("/ping", func(c *gin.Context){
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
}

demo

package main

import (
    "go-api/routes"
)

func main() {
    //启动服务器
    routes.Run()
}

访问即可看到返回

2、接下来我们准备Model层以及控制器写个案例

重点:ORM我们用的github.com/jinzhu/gorm 中文文档

准备SQL

CREATE TABLE `test_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT '' COMMENT '标签名称',
  `created_on` int(10) unsigned DEFAULT '0' COMMENT '创建时间',
  `created_by` varchar(100) DEFAULT '' COMMENT '创建人',
  `modified_on` int(10) unsigned DEFAULT '0' COMMENT '修改时间',
  `modified_by` varchar(100) DEFAULT '' COMMENT '修改人',
  `deleted_on` int(10) unsigned DEFAULT '0',
  `state` tinyint(3) unsigned DEFAULT '1' COMMENT '状态 0为禁用、1为启用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uiq-name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户管理';

app/models下新建 mysql.go

package models

import (
    "log"
    "fmt"
    "time"

    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
    
    "go-api/config"
)

type mysqlConfig struct{
	dbType string
	dbName string
	dbUser string
	dbPassword string
	dbHost string
	dbTablePrefix string
	LogMode bool
	MaxLifetime time.Duration
} 

var (
	db *gorm.DB
	dbConfig = &mysqlConfig{
		dbType:"mysql",
		dbName:config.MysqlSetting.MysqlName,
		dbUser:config.MysqlSetting.MysqlUser,
		dbPassword:config.MysqlSetting.MysqlPassword,
		dbHost:config.MysqlSetting.MysqlHost,
		dbTablePrefix:config.MysqlSetting.MysqlPrefix,
		MaxLifetime:config.MysqlSetting.MaxLifetime,
	}
)

type Model struct {
    ID int `gorm:"primary_key" json:"id"`
    CreatedOn int `json:"created_on"`
    ModifiedOn int `json:"modified_on"`
}

func init() {
    var (
        err error
	)
    db, err = gorm.Open(dbConfig.dbType, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local", 
        dbConfig.dbUser, 
        dbConfig.dbPassword,
		dbConfig.dbHost,  
        dbConfig.dbName))

		if err != nil {
			log.Println(err)
		}
		
		gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string  {
			return dbConfig.dbTablePrefix + defaultTableName;
		}
		
		db.SingularTable(true)//全局禁用表名复数
		db.LogMode(dbConfig.LogMode)//true  打印Log
		db.DB().SetMaxIdleConns(10)//最大空闲连接
		db.DB().SetMaxOpenConns(100)//最大数据库链接
		db.DB().SetConnMaxLifetime(dbConfig.MaxLifetime)//数据库链接最大生存时间
		//
}

func State() string{
	return fmt.Sprintf("%+v",db.DB().Stats())
}

func CloseDB() {
    defer db.Close()
}

func (model *Model) BeforeCreate(scope *gorm.Scope) error {
    scope.SetColumn("CreatedOn", time.Now().Unix())

    return nil
}

func (model *Model) BeforeUpdate(scope *gorm.Scope) error {
    scope.SetColumn("ModifiedOn", time.Now().Unix())
    return nil
}

新建user.go

package models

type User struct {
    Model

    Name string `json:"name"`
    CreatedBy string `json:"created_by"`
    ModifiedBy string `json:"modified_by"`
    State int `json:"state"`
}

func GetUsers(pageNum int, pageSize int, maps interface {}) (users []User) {
    db.Where(maps).Offset(pageNum).Limit(pageSize).Find(&users)
    
    return
}

func GetUserTotal(maps interface {}) (count int){
    db.Model(&User{}).Where(maps).Count(&count)

    return
}

func ExistUserByMaps(maps interface{}) bool {
    var user User
    db.Select("id").Where(maps).First(&user)
    if user.ID > 0 {
        return true
    }

    return false
}

func AddUser(Users map[string]interface{}) bool{
    user := User {
        Name : Users["Name"].(string),
        State : Users["State"].(int),
        CreatedBy : Users["CreatedBy"].(string),
    }
    db.Create(&user)
    return !db.NewRecord(user)
}

func ExistTagByID(id int) bool {
    var user User
    db.Select("id").Where("id = ?", id).First(&user)
    if user.ID > 0 {
        return true
    }

    return false
}

func DeleteUser(maps interface{}) bool {
    db.Where(maps).Delete(&User{})

    return true
}

func EditUser(id int, data interface {}) bool {
    db.Model(&User{}).Where("id = ?", id).Updates(data)

    return true
}

3、在app/controller下新增user.go

package controller

import (
	"github.com/gin-gonic/gin"
	"go-api/app/models"
)

func GetUsers(c *gin.Context) {
	maps := make(map[string]interface{})
    data := make(map[string]interface{})
	data["total"] = models.GetUserTotal(maps)
	data["list"]  = models.GetUsers(0,10,maps)
	c.JSON(200, gin.H{
		"status":  "200",
		"message": "查询成功",
		"data":    data,
	})
}

func GetUser(c *gin.Context) {

}

func AddUser(c *gin.Context) {

}

func EditUser(c *gin.Context) {

}

func DeleteUser(c *gin.Context){

}

新增api路由

package routes

import (
	"go-api/app/controller"

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

func apiRoute(r *gin.Engine){
	apiv1 := r.Group("/api/v1")
	{
		//获取用户列表
		apiv1.GET("/users", controller.GetUsers)
	}
}

编译后执行

go build -o test.exe .
./test.exe

下一章节我们会完善接口、并且封装服务层,以及使用gin自带的数据校验

系列文章