日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

go语言mysql框架_超级详细:Go语言框架Gin和Gorm实现一个完整的待办事项微服务...

發(fā)布時間:2024/8/23 数据库 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go语言mysql框架_超级详细:Go语言框架Gin和Gorm实现一个完整的待办事项微服务... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

本文通過一步一步的設(shè)計,最終實現(xiàn)一個完善的todo應(yīng)用。

我們使用GO框架Gin用戶路由控制和返回數(shù)據(jù)。使用Gorm用于操作數(shù)據(jù)庫。

讀者可根據(jù)本教程操作,最終實現(xiàn)列出的各項功能。

技術(shù)清單

本文中所涉及的技術(shù)內(nèi)容主要有以下幾種:Gin:輕量高效性能爆棚的WEB框架

Gorm:一個關(guān)系型數(shù)據(jù)庫的ORM工具包,避免直接SQL語句操作

MySQL:數(shù)據(jù)庫

curl工具,用于API接口數(shù)據(jù)測試

另外,使用的GO版本是go version go1.13.5 windows/amd64

對于第2,3條內(nèi)容,可使用以下指令安裝

對于工具curl,我們使用的是 git bash內(nèi)自帶的指令。如果是linux下用戶,開箱即用。

創(chuàng)建數(shù)據(jù)庫

本文使用MySQL數(shù)據(jù)庫裝載數(shù)據(jù)。本節(jié)我們僅需創(chuàng)建一個空的數(shù)據(jù)庫,就可以了。表結(jié)構(gòu)在下一節(jié)使用gorm遷移功能創(chuàng)建。

使用Navicat工具新建界面如下圖。

需要特別留意數(shù)據(jù)庫字符集編碼使用 utf8mb4,這個是MySQL真正的utf8,用于中文字符支持。

創(chuàng)建表模型

gorm中的Automigrate()操作,用于刷新數(shù)據(jù)庫中的表,使其保持最新。即讓數(shù)據(jù)庫之前存儲的記錄的表字段和程序中最新使用的表字段保持一致(只增不減)。

我們先建一個todos表模型。

type (

todoModel struct {

gorm.Model

Title string `json:"title"`

Completed int `json:"completed`

}

fmtTodo struct {

ID uint `json:"id"`

Title string `json:"title"`

Completed bool `json:"completed"`

}

)

其中 todoModel用于數(shù)據(jù)庫todos表。我們默認(rèn)繼承使用了gorm.Model的字段,主要包括以下幾個:

// gorm.Model 定義

type Model struct {

ID uint `gorm:"primary_key"`

CreatedAt time.Time

UpdatedAt time.Time

DeletedAt *time.Time

}

數(shù)據(jù)庫表會自動生成上述4個字段,并追加 title,completed兩個字段。模型名與表名不一致,我們手動指定表名:

// 指定表名

func (todoModel) TableName() string {

return "todos"

}

然后在代碼初始化過程中執(zhí)行遷移。

var db *gorm.DB

// 初始化

func init() {

var err error

var constr string

constr = fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", "root", "111213", "localhost", 3306, "05-gin-gorm-todo")

db, err = gorm.Open("mysql", constr)

if err != nil {

panic("數(shù)據(jù)庫連接失敗")

}

db.AutoMigrate(&todoModel{})

}

首先聲明一個 gorm.DB,用于數(shù)據(jù)庫操作。

在使用gorm包之前,需要導(dǎo)入。

import (

"github.com/jinzhu/gorm"

_ "github.com/jinzhu/gorm/dialects/mysql"

)

第二項我們僅導(dǎo)入而不使用。這個導(dǎo)入操作,gorm執(zhí)行了下述操作

import _ "github.com/go-sql-driver/mysql"

這樣我們無需重新手動處理包依賴關(guān)系。

MySQL的連接字符串是有特定格式的,這也是由底層 go-sql-driver/mysql 決定的參數(shù)配置項。其含義如下:

user:password@(hostname:port)/database_name?charset=utf8mb4&parseTime=True&loc=Local

此處我們使用的本地數(shù)據(jù)庫3306端口,root用戶,和 05-gin-gorm-todo 數(shù)據(jù)庫。

在執(zhí)行完整的程序之后,todos表會被自動遷移創(chuàng)建,其詳細(xì)參數(shù)如下圖。

這張表也是我們本文所操作的數(shù)據(jù)基礎(chǔ)。

規(guī)劃路由

依照restful風(fēng)格的API設(shè)計標(biāo)準(zhǔn),我們規(guī)劃了5個路由,涵蓋了一個todo列表清單的增刪改查功能。

func main() {

r := gin.Default()

v1 := r.Group("/api/v1/todo")

{

v1.POST("/", add) // 添加新條目

v1.GET("/", all) // 查詢所有條目

v1.GET("/:id", take) // 獲取單個條目

v1.PUT("/:id", update) // 更新單個條目

v1.DELETE("/:id", del) // 刪除單個條目

}

r.Run(":9089")

}

這個是最終會使用到的main函數(shù),使用了gin提供的路由功能。為了擴展方便,我們使用了gin路由的Group功能,將版本v1的所有路由集中處理。

其中,訪問的方法跟別使用 POST表示添加,GET表示查詢,PUT表是更新,DELETE表示刪除,這是restful API設(shè)計的一般性方法。

API功能

上一節(jié)規(guī)劃的路由中,我們聲明了5個函數(shù),本節(jié)逐一實現(xiàn)這5個函數(shù)。注意API返回數(shù)據(jù)都是JSON格式。

為了統(tǒng)一返回狀態(tài)碼,對于正確響應(yīng)的,返回HTTP CODE = 200。JSON數(shù)據(jù)的正常與否,使用兩個常量表示,如下:

const (

JSON_SUCCESS int = 1

JSON_ERROR int = 0

)

成功返回1,失敗返回0。

1 - 添加條目 add

主要的功能,是拿到POST表單提交的數(shù)據(jù),并寫入數(shù)據(jù)庫,成功則返回信息通知,失敗則給出相應(yīng)提示。

// 創(chuàng)建TODO條目func add(c *gin.Context) {

completed, _ := strconv.Atoi(c.PostForm("completed"))

todo := todoModel{Title: c.PostForm("title"), Completed: completed}

db.Save(&todo)

c.JSON(http.StatusOK, gin.H{

"status": JSON_SUCCESS,

"message": "創(chuàng)建成功",

"resourceId": todo.ID,

})

}

注意我們對于POST提供的字段 completed 進(jìn)行了轉(zhuǎn)換,因為表單數(shù)據(jù)默認(rèn)都是字符串類型,而todoModel內(nèi)Completed是int類型,所以需要進(jìn)行轉(zhuǎn)換。

2 - 獲取所有條目

不接受任何參數(shù),默認(rèn)給出所有的條目內(nèi)容。

// 獲取所有條目func all(c *gin.Context) {

var todos []todoModel

var _todos []fmtTodo

db.Find(&todos)

// 沒有數(shù)據(jù)if len(todos) <= 0 {

c.JSON(http.StatusOK, gin.H{

"status": JSON_ERROR,

"message": "沒有數(shù)據(jù)",

})

return

}

// 格式化for _, item := range todos {

completed := false

if item.Completed == 1 {

completed = true

} else {

completed = false

}

_todos = append(_todos, fmtTodo{

ID: item.ID,

Title: item.Title,

Completed: completed,

})

}

c.JSON(http.StatusOK, gin.H{

"status": JSON_SUCCESS,

"message": "ok",

"data": _todos,

})

}

為了API返回數(shù)據(jù)的便于使用,我們使用了一個結(jié)構(gòu)體 fmtTodo 用于將結(jié)構(gòu)體 todoModel 的數(shù)據(jù)進(jìn)行格式化。如果沒有查詢到任何數(shù)據(jù),返回狀態(tài)碼 status = 0。

3 - 獲取單個條目

在路由中附加的id,可以調(diào)用此路由,用于返回單條數(shù)據(jù)。

// 根據(jù)id獲取一個條目func take(c *gin.Context) {

var todo todoModel

todoID := c.Param("id")

db.First(&todo, todoID)

if todo.ID == 0 {

c.JSON(http.StatusNotFound, gin.H{

"status": JSON_ERROR,

"message": "條目不存在",

})

return

}

completed := false

if todo.Completed == 1 {

completed = true

} else {

completed = false

}

_todo := fmtTodo{

ID: todo.ID,

Title: todo.Title,

Completed: completed,

}

c.JSON(http.StatusOK, gin.H{

"status": JSON_SUCCESS,

"message": "ok",

"data": _todo,

})

}

根據(jù)ID查詢數(shù)據(jù),如果存在就返回,并使用fmtTodo進(jìn)行格式化;如果不存在,狀態(tài)碼等于0。

4 - 更新單個條目

已經(jīng)存在的數(shù)據(jù),根據(jù)ID對其內(nèi)容進(jìn)行修改。如果ID不存在,返回錯誤信息。

// 更新一個條目func update(c *gin.Context) {

var todo todoModel

todoID := c.Param("id")

db.First(&todo, todoID)

if todo.ID == 0 {

c.JSON(http.StatusNotFound, gin.H{

"status": JSON_ERROR,

"message": "條目不存在",

})

return

}

db.Model(&todo).Update("title", c.PostForm("title"))

completed, _ := strconv.Atoi(c.PostForm("completed"))

db.Model(&todo).Update("completed", completed)

c.JSON(http.StatusOK, gin.H{

"status": JSON_SUCCESS,

"message": "更新成功",

})

}

5 - 刪除單個條目

根據(jù)ID查詢是否存在,如果存在就進(jìn)行刪除。

// 刪除條目func del(c *gin.Context) {

var todo todoModel

todoID := c.Param("id")

db.First(&todo, todoID)

if todo.ID == 0 {

c.JSON(http.StatusOK, gin.H{

"status": JSON_ERROR,

"message": "條目不存在",

})

return

}

db.Delete(&todo)

c.JSON(http.StatusOK, gin.H{

"status": JSON_SUCCESS,

"message": "刪除成功!",

})

}

以上就是5個方法的具體實現(xiàn),只能用作demo,而不能用于生產(chǎn)。因為表單數(shù)據(jù)的有效性檢測,我們在代碼中并沒有實現(xiàn)。這在線上是絕對不允許的。

還有一些數(shù)據(jù)的鑒權(quán),用戶身份權(quán)限鑒定,本示例中都沒有。

使用curl測試

完成以上步驟,該todo清單功能基本完善,我們使用

go build main.go

進(jìn)行編譯,如果不出錯,編譯通過后,會生成 main.exe 文件。我們在命令行直接運行該文件,結(jié)果如下圖。

下面我們對五個url分別進(jìn)行測試。

首先是獲取所有的條目,

curl -s -X GET http://localhost:9089/api/v1/todo/

這會命中第二條路由規(guī)則,返回值如下:

{"message":"沒有數(shù)據(jù)","status":0}

暫時沒有數(shù)據(jù)。接著添加一個條目:

curl -s -X POST -d "title=Talk is cheap, show me the code." -d "completed=0" http://localhost:9089/api/v1/todo/

執(zhí)行成功返回數(shù)據(jù)

{"message":"創(chuàng)建成功","resourceId":8,"status":1}

接著我們再查詢所有的條目,看看能否找到。返回結(jié)果如下:

{"data":[{"id":8,"title":"Talk is cheap, show me the code.","completed":false}],"message":"ok","status":1}

為了演示方便,我們再隨機寫入幾條數(shù)據(jù),然后測試單條數(shù)據(jù)查詢,修改,和刪除。

curl -s -X POST -d "title=Life is short, I use python." -d "completed=0" http://localhost:9089/api/v1/todo/

curl -s -X POST -d "title=Zen of Golang." -d "completed=0" http://localhost:9089/api/v1/todo/

curl -s -X POST -d "title=Do not repeat yourself." -d "completed=0" http://localhost:9089/api/v1/todo/

然后獲取所有的條目

curl -s -X GET http://localhost:9089/api/v1/todo/

結(jié)果JSON數(shù)組格式化輸出如下:

測試獲取單條數(shù)據(jù),這里使用id=10這一條,執(zhí)行如下指令

curl -s -X GET http://localhost:9089/api/v1/todo/10

返回結(jié)果如下:

{"data":{"id":10,"title":"Zen of Golang.","completed":false},"message":"ok","status":1}

測試修改該條數(shù)據(jù),設(shè)置completed=1,為已完成狀態(tài)。

curl -s -X PUT -d "title=Zen of Golang." -d "completed=1" http://localhost:9089/api/v1/todo/10

執(zhí)行成功返回:

{"message":"更新成功!","status":1}

注意更新操作使用的method = PUT。會命中第4條路由規(guī)則。

下面刪除id=10的條目,使用以下指令:

curl -s -X DELETE http://localhost:9089/api/v1/todo/10

執(zhí)行成功后返回結(jié)果:

{"message":"刪除成功!","status":1}

OK,上面所有的路由都已經(jīng)測試完畢,看服務(wù)器端的訪問歷史,大致如下圖:

注意到有一條是數(shù)據(jù)庫連接的自動釋放,這是由MySQL設(shè)置的連接超時時間決定的,超期閑置則釋放。如果有新的連接請求,重新建立。這可以節(jié)約資源。

關(guān)鍵點總結(jié)

在測試上述功能的時候,列出一些初學(xué)者可能會犯的錯。

1 - 數(shù)據(jù)庫連接失敗

一定要確保連接字符串書寫正確,賬號密碼書寫正確,數(shù)據(jù)庫IP地址和端口號正確,還有數(shù)據(jù)庫名稱對應(yīng)。如果始終不能連接成長,可以嘗試單獨拿出來數(shù)據(jù)庫連接進(jìn)行測試,直到通過。

2 - 路由地址

根據(jù)設(shè)定的路由規(guī)則,正確地書寫路由地址,還有傳送參數(shù)方法,這樣才能在程序中獲取到提交的數(shù)據(jù)。

比如使用POST,傳送的表單數(shù)據(jù)使用 c.PostForm 可以獲取到。而 c.Param 則用于獲取路由中 “/:id” id 這個位置參數(shù)。

3 - curl測試工具使用

注意使用請求方式 -X 參數(shù),還有POST中使用的 -d 參數(shù)選項。

結(jié)語

以上內(nèi)容使用兩個成熟的包,快速地創(chuàng)建了一個待辦清單的微服務(wù)。可以看到Go語言生態(tài)日臻完善,優(yōu)秀的框架頻出,給開發(fā)帶來了很高的效率。

另外,GO語言的易于書寫特性,接近與腳本語言的表達(dá)力,還有嚴(yán)格的數(shù)據(jù)類型檢測,將不少低級的錯誤排除在編譯階段。

Happy coding :-)

【本文由 @程序員小助手 發(fā)布,持續(xù)分享編程與程序員成長相關(guān)的內(nèi)容,歡迎關(guān)注】

總結(jié)

以上是生活随笔為你收集整理的go语言mysql框架_超级详细:Go语言框架Gin和Gorm实现一个完整的待办事项微服务...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。