文/朱季謙java
本文搭建準備環境:Gin+Gorm+MySql。mysql
Gin是Go語言的一套WEB框架,在學習一種陌生語言的陌生框架,最好的方式,就是用咱們熟悉的思惟去學。做爲一名後端Java開發,在最初入門時,最熟悉的莫過於MVC分層結構,能夠簡單概括成controller層,model層,dao層,而在SpringBoot框架裏,大概也常常看到如下的分層結構——git
這個結構分爲java根目錄與resources資源目錄。github
在學習Go語言的Gin框架時,是否也能夠參照這樣的分層結構來搭建一套簡單的後端系統呢。golang
答案是,確定的。sql
接下來,咱們就按照這個MVC分層結構,搭建一套基於Gin+Gorm框架的Go語言後端。數據庫
搭建以前,先簡單介紹一下Gin和Gorm分別是什麼。json
Gin是一個golang的WEB框架,很輕量,依賴到不多,有些相似Java的SpringMVC,經過路由設置,能夠將請求轉發到對應的處理器上。後端
Gorm是Go語言的ORM框架,提供一套對數據庫進行增刪改查的接口,使用它,就能夠相似Java使用Hibernate框架同樣,可對數據庫進行相應操做。mybatis
若要用到這兩套框架,就須要import依賴進來,依賴進來前,須要Go命令安裝Gin和Gorm。
go get -u github.com/gin-gonic/gin go get -u github.com/jinzhu/gorm
最好放在GOPATH目錄下。
個人GOPATH目錄在C:\Users\Administrator\go下:
經過Go命令安裝的依賴包放在這個目錄底下C:\Users\Administrator\go\src下:
如今,咱們就參考SpringBoot的分層結構,搭建一套MVC分層結構系統。
先建立一個Go項目,這裏,我取名爲go-admin,底下建立一個go目錄,用於存放Go代碼;一個resources資源目錄,存放配置文件,結構以下——
go根目錄底下,建立controller、service、dao、entity包,另外,還須要一個router包,用於存放路由文件,可能你對路由文件不是很理解,那麼,你能夠簡單理解爲,這個路由的做用,就相似SpringMVC的@RequestMapping("/user")和@GetMapping("/list")註解組合起到的做用,經過路由,就能夠找到須要調用的後端方法。建立完這些包後,若在SpringBoot項目裏,是否還缺乏一個xxxxxApplication.java的啓動類,沒錯,在Go裏,一樣須要一個啓動類,該啓動類文件能夠直接命名爲main.go。
建立以上包與類後,go根目錄底下結構以下:
接下來,是在resources資源目錄建立一個application.yaml配置文件,固然,這個配置文件能夠隨便命名,不用像SpringBoot那樣須要考慮其命名背後所表明的優先級。
這個配置文件裏,就存放須要用到的Mysql數據庫鏈接信息:
url: 127.0.0.1 userName: root password: root dbname: example post: 3306
這些基礎工做作好後,就能夠填充代碼了。
在dao層下,創建一個mysql.go文件,這個文件在dao的包下,最初的效果以下
按照以往jdbc鏈接數據庫的步驟,首先須要加載jdbc驅動程序,而後再建立數據庫的鏈接,其實,在Go鏈接數據庫,一樣須要相似這樣的操做。
首先,須要導入數據庫驅動程序。
Gorm已經包含了驅動程序,只須要將它導入進來便可:
import _ "github.com/jinzhu/gorm/dialects/mysql"
進入到這個依賴包的源碼,根據命名就能夠看到出,這是一個go語言的mysql驅動包——
除此以外,還提供了mssql、postgres、sqlite的驅動包。
底層使用到的是GORM 框架,天然也要把它依賴進來:
import "github.com/jinzhu/gorm"
另外,還須要依賴如下幾個包,用於讀取yaml配置文件數據與拼接成url字符串:
import "io/ioutil" import "gopkg.in/yaml.v2" import "fmt"
當依賴的包過多時,咱們能夠統一放到一個()號裏,例如這樣:
import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" "io/ioutil" "gopkg.in/yaml.v2" "fmt" )
到這一步,效果以下:
這裏爆紅色是正常的,Go語言與Java不一樣的一個地方是,若依賴進來的包,沒有被用到話,會直接出現紅色異常提示,後面寫到用到它們的代碼時,就正常了。
接下來,定義一個用於接收yaml配置參數的struct結構體,你能夠簡單將它理解爲Java的類。
type conf struct { Url string `yaml:"url"` UserName string `yaml:"userName"` Password string `yaml:"password"` DbName string `yaml:"dbname"` Port string `yaml:"post"` }
而後提供一個讀取解析該yaml配置的方法,將讀取到的配置參數數據轉換成上邊的結構體conf
func (c *conf) getConf() *conf { //讀取resources/application.yaml文件 yamlFile, err := ioutil.ReadFile("resources/application.yaml") //若出現錯誤,打印錯誤提示 if err != nil { fmt.Println(err.Error()) } //將讀取的字符串轉換成結構體conf err = yaml.Unmarshal(yamlFile, c) if err != nil { fmt.Println(err.Error()) } return c }
後面能夠經過debug觀察一下,這個返回的c變量,它就相似Java的對象,裏邊是key-value形式的值——
最後,就能夠根據這些解析到的配置參數,用來驅動鏈接數據庫了。
建立一個相似舊版mybatis全局的SqlSession變量,就取名爲SqlSession便可,該變量起到做用於mybatis的SqlSession實例相似,在數據庫驅動鏈接成功後,便可提供select/insert/update/delete方法。
var SqlSession *gorm.DB
而後定義一個初始化鏈接數據庫的方法,該方法用於在啓動項目時執行——
func InitMySql()(err error) { var c conf //獲取yaml配置參數 conf:=c.getConf() //將yaml配置參數拼接成鏈接數據庫的url dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.UserName, conf.Password, conf.Url, conf.Port, conf.DbName, ) //鏈接數據庫 SqlSession,err =gorm.Open("mysql",dsn) if err !=nil{ panic(err) } //驗證數據庫鏈接是否成功,若成功,則無異常 return SqlSession.DB().Ping() }
最後,還須要提供一個能夠關閉數據庫鏈接的方法——
func Close() { SqlSession.Close() }
到這裏,咱們就完成了Dao層的搭建,該層裏的代碼主要負責鏈接數據庫,建立一個取名爲SqlSession全局的*gorm.DB變量,該變量做用相似SqlSession,提供了操做數據庫的方法,最後,整塊dao層的mysql.go代碼就以下:
package dao import ( "github.com/jinzhu/gorm" "io/ioutil" ) import ( "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" "io/ioutil" "gopkg.in/yaml.v2" "fmt" ) //指定驅動 const DRIVER = "mysql" var SqlSession *gorm.DB //配置參數映射結構體 type conf struct { Url string `yaml:"url"` UserName string `yaml:"userName"` Password string `yaml:"password"` DbName string `yaml:"dbname"` Port string `yaml:"post"` } //獲取配置參數數據 func (c *conf) getConf() *conf { //讀取resources/application.yaml文件 yamlFile, err := ioutil.ReadFile("resources/application.yaml") //若出現錯誤,打印錯誤提示 if err != nil { fmt.Println(err.Error()) } //將讀取的字符串轉換成結構體conf err = yaml.Unmarshal(yamlFile, c) if err != nil { fmt.Println(err.Error()) } return c } //初始化鏈接數據庫,生成可操做基本增刪改查結構的變量 func InitMySql()(err error) { var c conf //獲取yaml配置參數 conf:=c.getConf() //將yaml配置參數拼接成鏈接數據庫的url dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", conf.UserName, conf.Password, conf.Url, conf.Port, conf.DbName, ) //鏈接數據庫 SqlSession,err =gorm.Open(DRIVER,dsn) if err !=nil{ panic(err) } //驗證數據庫鏈接是否成功,若成功,則無異常 return SqlSession.DB().Ping() } //關閉數據庫鏈接 func Close() { SqlSession.Close() }
Gorm是全特性的ORM框架,即對象關係映射,這樣,就須要相似Java那樣創建與數據庫映射的類,在Go語言當中,咱們稱之爲結構體。
首先,先建立一張用於驗證的數據庫表結構——
CREATE TABLE `sys_user` ( `id` int(50) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL COMMENT '用戶名', `nick_name` varchar(150) DEFAULT NULL COMMENT '暱稱', `avatar` varchar(150) DEFAULT NULL COMMENT '頭像', `password` varchar(100) DEFAULT NULL COMMENT '密碼', `email` varchar(100) DEFAULT NULL COMMENT '郵箱', `mobile` varchar(100) DEFAULT NULL COMMENT '手機號', `create_time` bigint(50) DEFAULT NULL COMMENT '更新時間', `del_status` tinyint(4) DEFAULT '0' COMMENT '是否刪除 -1:已刪除 0:正常', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='用戶表';
而後建立一個User.go文件,裏邊定義一個User結構體——
type User struct { Id int `json:"id"` Name string `json:"name"` NickName string `json:"nickName"` Avatar string `json:"avatar"` Password string `json:"password"` Email string `json:"email"` Mobile string `json:"mobile"` DelStatus int `json:"delStatus"` CreateTime int64 `json:"createTime"` }
注意一點,這裏須要明確指出,其struct結構體映射到哪一張表,若是沒有顯示指出,它會默認生成一張命名爲users的數據庫表——
// 數據庫代表自定義,默認爲model的複數形式,好比這裏默認爲 users func (User) TableName() string { return "sys_user" }
到這一步,咱們就完成了user模型關係創建。
package entity // 數據庫代表自定義,默認爲model的複數形式,好比這裏默認爲 users func (User) TableName() string { return "sys_user" } type User struct { Id int `json:"id"` Name string `json:"name"` NickName string `json:"nickName"` Avatar string `json:"avatar"` Password string `json:"password"` Email string `json:"email"` Mobile string `json:"mobile"` DelStatus int `json:"delStatus"` CreateTime int64 `json:"createTime"` }
在service層創建一個User的service類,命名爲UserService.go。
這裏,須要引入兩個依賴,一個是dao層建立的全局SqlSession,用於操做數據庫;一個是User類,用於接收數據庫對應表結構的數據。
import ( "go-admin/go/dao" "go-admin/go/entity" )
接下來,就能夠基於SqlSession獲取到的API接口,對數據庫進行簡單的增刪改查操做了。
1.添加User信息
/** 新建User信息 */ func CreateUser(user *entity.User)(err error) { if err = dao.SqlSession.Create(user).Error;err!=nil{ return err } return }
2.查詢全部的User記錄
/** 獲取user集合 */ func GetAllUser()(userList []*entity.User,err error) { if err:=dao.SqlSession.Find(&userList).Error;err!=nil{ return nil,err } return }
3.根據id刪除對應的User信息
/** 根據id刪除user */ func DeleteUserById(id string)(err error){ err = dao.SqlSession.Where("id=?",id).Delete(&entity.User{}).Error return }
4.根據id查詢用戶User
/** 根據id查詢用戶User */ func GetUserById(id string)(user *entity.User,err error) { if err = dao.SqlSession.Where("id=?",id).First(user).Error;err!=nil{ return nil,err } return }
5.更新用戶信息
/** 更新用戶信息 */ func UpdateUser(user * entity.User)(err error) { err = dao.SqlSession.Save(user).Error return }
UserService.go的完整代碼以下:
package service import ( "go-admin/go/dao" "go-admin/go/entity" ) /** 新建User信息 */ func CreateUser(user *entity.User)(err error) { if err = dao.SqlSession.Create(user).Error;err!=nil{ return err } return } /** 獲取user集合 */ func GetAllUser()(userList []*entity.User,err error) { if err:=dao.SqlSession.Find(&userList).Error;err!=nil{ return nil,err } return } /** 根據id刪除user */ func DeleteUserById(id string)(err error){ err = dao.SqlSession.Where("id=?",id).Delete(&entity.User{}).Error return } /** 根據id查詢用戶User */ func GetUserById(id string)(user *entity.User,err error) { if err = dao.SqlSession.Where("id=?",id).First(user).Error;err!=nil{ return nil,err } return } /** 更新用戶信息 */ func UpdateUser(user * entity.User)(err error) { err = dao.SqlSession.Save(user).Error return }
在controller層創建一個UserController.go類,相似Java的controller,主要用於根據url跳轉執行到對應路徑的方法。
首先,引入須要用到的依賴包,
import ( //須要用到的結構體 "go-admin/go/entity" //gin框架的依賴 "github.com/gin-gonic/gin" //http鏈接包 "net/http" //service層方法 "go-admin/go/service" )
接下來,能夠實現增刪改查的controller方法了。
1.實現新增User的方法
func CreateUser(c *gin.Context) { //定義一個User變量 var user entity.User //將調用後端的request請求中的body數據根據json格式解析到User結構變量中 c.BindJSON(&user) //將被轉換的user變量傳給service層的CreateUser方法,進行User的新建 err:=service.CreateUser(&user) //判斷是否異常,無異常則返回包含200和更新數據的信息 if err!=nil{ c.JSON(http.StatusBadRequest,gin.H{"error":err.Error()}) }else { c.JSON(http.StatusOK,gin.H{ "code":200, "msg":"success", "data":user, }) } }
2.查詢User的方法
func GetUserList(c *gin.Context) { todoList,err :=service.GetAllUser() if err!=nil{ c.JSON(http.StatusBadRequest,gin.H{"error":err.Error()}) }else { c.JSON(http.StatusOK,gin.H{ "code":200, "msg":"success", "data":todoList, }) } }
routes層新建一個Routers.go文件。
首先,一樣須要引入須要用到的依賴——
import ( "go-admin/go/controller" "github.com/gin-gonic/gin" )
而後搭建一個初始化路由的操做,將路由統一存放到數據user的group組裏,這樣能夠比較方便區分這些路由數據哪一個controller類的。
Routers.go文件完整代碼以下:
package routes import ( "go-admin/go/controller" "github.com/gin-gonic/gin" ) func SetRouter() *gin.Engine { r :=gin.Default() /** 用戶User路由組 */ userGroup :=r.Group("user") { //增長用戶User userGroup.POST("/users",controller.CreateUser) //查看全部的User userGroup.GET("/users",controller.GetUserList) //修改某個User userGroup.PUT("/users/:id",controller.UpdateUser) //刪除某個User userGroup.DELETE("/users/:id",controller.DeleteUserById) } return r }
最後一步,就是創建main的啓動類了,須要注意一點是,go的啓動類,必須命名在package main的包下,不然沒法進行啓動。
首先,仍是須要先引入依賴,main啓動類須要用到dao、entity、routers以及mysql驅動包。
import ( "go-admin/go/dao" "go-admin/go/entity" "go-admin/go/routes" _ "github.com/jinzhu/gorm/dialects/mysql" )
啓動方法裏的代碼主要以下,即前邊搭建的東西,這裏都有用到了——
func main() { //鏈接數據庫 err :=dao.InitMySql() if err !=nil{ panic(err) } //程序退出關閉數據庫鏈接 defer dao.Close() //綁定模型 dao.SqlSession.AutoMigrate(&entity.User{}) //註冊路由 r :=routes.SetRouter() //啓動端口爲8085的項目 r.Run(":8081") }
到這一步,就能夠啓動項目了,正常狀況下,啓動成功會顯示如下日誌信息——
到這一步,基於Gin+Gorm框架搭建MVC模式的Go後端系統,就初步搭建完成了。
最後,代碼已經上傳到GitHub:https://github.com/z924931408/go-admin.git
歡迎關注公衆號,關於思考,關於文化,關於成長——