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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM