zoukankan      html  css  js  c++  java
  • Gin实战:Gin+Mysql简单的Restful风格的API(二)

    上一篇介绍了Gin+Mysql简单的Restful风格的API,但代码放在一个文件中,还不属于restful风格,接下来将进行进一步的封装。

    目录结构

    ☁  gin_restful2  tree
    .
    ├── api
    │   └── users.go
    ├── db
    │   └── mysql.go
    ├── main.go
    ├── models
    │   └── users.go
    └── router.go

    api文件夹存放我们的handler函数,用于逻辑处理,models文件夹用来存放我们的数据模型。

    myql.go的包代码如下:

    package db
    
    import (
        "database/sql"
        _ "github.com/go-sql-driver/mysql"
        "log"
    )
    
    var SqlDB *sql.DB
    func init()  {
        var err error
        SqlDB, err = sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/test?charset=utf8mb4")
        if err != nil {
            log.Fatal(err.Error())
        }
        err = SqlDB.Ping()
        if err != nil {
            log.Fatal(err.Error())
        }
    }

    因为我们需要在别的地方使用SqlDB这个变量,因此依照golang的习惯,变量名必须大写开头。

    数据model封装

    修改models文件夹下的users.go,把对应的Person结构及其方法移到这里:

    package models
    import (
        "gin_restful2/db"
        "log"
    )
    
    type Person struct {
        Id int `json:"id" form:"id"`
        Name string `json:"name" form:"name"`
        Telephone string `json:"telephone" form:"telephone"`
    }
    
    //插入
    func (person *Person) Create() int64 {
        rs, err := db.SqlDB.Exec("INSERT into users (name, telephone) value (?,?)", person.Name, person.Telephone)
        if err != nil{
            log.Fatal(err)
        }
        id, err := rs.LastInsertId()
        if err != nil{
            log.Fatal(err)
        }
        return id
    }
    
    //查询一条记录
    func (p *Person) GetRow() (person Person, err error)  {
        person = Person{}
        err = db.SqlDB.QueryRow("select id,name,telephone from users where id = ?", p.Id).Scan(&person.Id, &person.Name, &person.Telephone)
        return
    }
    
    //查询所有记录
    func (person *Person) GetRows() (persons []Person, err error) {
        rows, err := db.SqlDB.Query("select id,name,telephone from users")
        for rows.Next(){
            person := Person{}
            err := rows.Scan(&person.Id, &person.Name, &person.Telephone)
            if err != nil {
                log.Fatal(err)
            }
            persons = append(persons, person)
        }
        rows.Close()
        return
    }
    
    //修改
    func (person *Person) Update() int64{
        rs, err := db.SqlDB.Exec("update users set telephone = ? where id = ?", person.Telephone, person.Id)
        if err != nil {
            log.Fatal(err)
        }
        rows, err := rs.RowsAffected()
        if err != nil {
            log.Fatal(err)
        }
        return  rows
    }
    
    //删除一条记录
    func Delete(id int) int64  {
        rs, err := db.SqlDB.Exec("delete from users where id = ?", id)
        if err != nil {
            log.Fatal()
        }
        rows, err := rs.RowsAffected()
        if err != nil {
            log.Fatal()
        }
        return rows
    }

    handler

    然后把具体的handler函数封装到api包中,因为handler函数要操作数据库,所以会引用model包,api/users.go代码如下:

    package api
    
    import (
        "github.com/gin-gonic/gin"
        "net/http"
        "fmt"
        ."gin_restful2/models"
        "strconv"
    )
    
    //index
    func IndexUsers(c *gin.Context)  {
        c.String(http.StatusOK, "It works")
    }
    
    //增加一条记录
    func AddUsers(c *gin.Context)  {
        name := c.Request.FormValue("name")
        telephone := c.Request.FormValue("telephone")
        person := Person{
            Name:name,
            Telephone:telephone,
        }
        id := person.Create()
        msg := fmt.Sprintf("insert successful %d", id)
        c.JSON(http.StatusOK, gin.H{
            "msg": msg,
        })
    }
    
    //获得一条记录
    func GetOne(c *gin.Context)  {
        ids := c.Param("id")
        id, _ := strconv.Atoi(ids)
        p := Person{
            Id:id,
        }
        rs, _ := p.GetRow()
        c.JSON(http.StatusOK, gin.H{
            "result": rs,
        })
    }
    
    //获得所有记录
    func GetAll(c *gin.Context)  {
        p := Person{}
        rs, _ := p.GetRows()
        c.JSON(http.StatusOK, gin.H{
            "list": rs,
        })
    }
    
    func UpdateUser(c *gin.Context)  {
        ids := c.Request.FormValue("id")
        id, _ := strconv.Atoi(ids)
        telephone := c.Request.FormValue("telephone")
        person := Person{
            Id:id,
            Telephone:telephone,
        }
        row := person.Update()
        msg := fmt.Sprintf("updated successful %d", row)
        c.JSON(http.StatusOK, gin.H{
            "msg": msg,
        })
    }
    
    //删除一条记录
    func DelUser(c *gin.Context)   {
        ids := c.Request.FormValue("id")
        id, _ := strconv.Atoi(ids)
        row := Delete(id)
        msg := fmt.Sprintf("delete successful %d", row)
        c.JSON(http.StatusOK, gin.H{
            "msg": msg,
        })
    }

    路由

    最后就是把路由抽离出来,修改router.go,我们在路由文件中封装路由函数

    package main
    
    import (
        "github.com/gin-gonic/gin"
        . "gin_restful2/api"
    )
    
    func initRouter() *gin.Engine {
        router := gin.Default()
        router.GET("/", IndexUsers) //http://localhost:8806
    
        //路由群组
        users := router.Group("api/v1/users")
        {
            users.GET("", GetAll) //http://localhost:8806/api/v1/users
            users.POST("/add", AddUsers) //http://localhost:8806/api/v1/users/add
            users.GET("/get/:id", GetOne) //http://localhost:8806/api/v1/users/get/5
            users.POST("/update", UpdateUser)
            users.POST("/del", DelUser)
        }
    
        return router
    }

    app入口

    最后就是main函数的app入口,将路由导入,同时我们要在main函数结束的时候,关闭全局的数据库连接池:

    main.go

    package main
    
    import (
        "gin_restful2/db"
    )
    
    func main() {
        defer db.SqlDB.Close()
        router := initRouter()
        router.Run(":8806")
    }

    至此,我们就把简单程序进行了更好的组织。当然,golang的程序组织依包为基础,不拘泥,根据具体的应用场景可以组织。

    此时运行项目,不能像之前简单的使用go run main.go,因为包main包含main.go和router.go的文件,因此需要运行go run *.go命令编译运行。如果是最终编译二进制项目,则运行go build -o app

  • 相关阅读:
    CF869E The Untended Antiquity 解题报告
    Walk 解题报告
    CF911F Tree Destruction 解题报告
    P4397 [JLOI2014]聪明的燕姿
    洛谷 P2329 [SCOI2005]栅栏 解题报告
    洛谷 P3747 [六省联考2017]相逢是问候 解题报告
    set-erase
    set-empty
    set-empty
    set-end
  • 原文地址:https://www.cnblogs.com/liuzhongchao/p/9261933.html
Copyright © 2011-2022 走看看