上篇文章中咱們在使用的開發環境中增長了MySQL
容器,而後介紹了使用database/sql
標準庫結合數據庫驅動包進行數據庫操做的方法。不過它們是相對偏底層的軟件包。實際開發常常會使用一些在它的基礎上封裝的 ORM
庫。ORM
的查詢使用起來更簡單些,語法更富表達力。這篇文章咱們主要探究下面這些內容。mysql
gorm
的基本用法ORM
的使用gorm
是一個出色的,對開發人員友好的 Golang
ORM
庫,其支持的特性包括:git
使用以下命令進行安裝:github
go get -u github.com/jinzhu/gorm
複製代碼
咱們在項目根目錄下新建以下目錄:web
http_demo
|
└───model
│ └───dao
│ │ init.go
│ └───────table
│ │ user.go
複製代碼
在 Go 中包以目錄的形式來組織,因此model
包中存放全部數據模型,dao
表明數據訪問對象,存放數據庫CRUD
方法的封裝,其中的init.go
存放dao
包的初始化函數主要是用來在加載包後鏈接上數據庫。table
包裏放與數據表對應的模型定義(使用 ORM 以前要先定義模型與數據庫中的表對應),在示例裏咱們會定義一個User
模型放在user.go
文件中。sql
規劃完目錄後就能夠在各部分寫相應的代碼了,首先來看使用gorm
鏈接數據庫。docker
咱們在dao
包的init.go
中加入包的初始化邏輯進行數據庫鏈接,初始化函數會在dao
包第一次被導入時執行,因爲gorm
文檔鏈接數據庫的例子太簡單,參考價值不大,咱們根據項目須要作些簡單封裝,init.go
中的代碼以下所示:shell
package dao
import (
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"time"
)
var _DB *gorm.DB
func DB() *gorm.DB {
return _DB
}
func init() {
_DB = initDB()
}
func initDB() *gorm.DB {
// In our docker dev environment use
// db, err := gorm.Open("mysql", "go_web:go_web@tcp(database:3306)/go_web?charset=utf8&parseTime=True&loc=Local")
db, err := gorm.Open("mysql", "go_web:go_web@tcp(localhost:33063)/go_web?charset=utf8&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
db.DB().SetMaxOpenConns(100)
db.DB().SetMaxIdleConns(10)
db.DB().SetConnMaxLifetime(time.Second * 300)
if err = db.DB().Ping(); err != nil {
panic(err)
}
return db
}
複製代碼
代碼很簡單,你們實操的時候根據本身的MySQL
配置更改代碼裏面的配置就好了。惟一說明一點的是,若是使用了咱們提提供的Docker
環境,在鏈接數據庫時host
要改成database:3306
,由於我在容器環境裏將MySQL
容器的服務名定義成了database
,在運行了Go
的app
容器須要用服務名訪問容器網絡中的其餘容器。關於容器環境的詳細配置請你們查看Go Web編程--應用數據庫 中的描述。數據庫
使用模型訪問數據庫的表以前咱們須要先定義對應的模型。咱們示例中如今只有一個users
表,接下來咱們在table
包中添加users
表的模型定義並放置在user.go
文件中。編程
package table
import "time"
type User struct {
Id int64 `gorm:"column:id;primary_key"`
UserName string `gorm:"column:username"`
Secret string `gorm:"column:secret;type:varchar(1000)"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
}
// TableName sets the insert table name for this struct type
func (m *User) TableName() string {
return "users"
}
複製代碼
關於模型的 CRUD,建議將單個模型的CRUD
放在dao
包的單個文件中,這樣方便之後代碼的管理。這裏多說一點,建議不要直接用controller
或者叫handler
包直接訪問dao
包,而是在中間加一層logic
包,把邏輯放在這一層。這樣對代碼的管理、複用性都有幫助。bash
由於數據庫的 CRUD 有不少種操做,本文的目的是幫助你們快速開始使用gorm
因此我就只放簡單的 CRUD 作演示了。你們按照這裏步驟引入gorm
後用到其餘的數據庫操做了直接去官方文檔裏查一查就好。
在dao
包中新建user.go
用來存放User
模型的操做方法。
package dao
import "example.com/http_demo/model/dao/table"
func CreateUser(user *table.User) (err error) {
err = DB().Create(user).Error
return
}
func GetUserById(userId int64) (user *table.User, err error) {
user = new(table.User)
err = DB().Where("id = ?", userId).First(user).Error
return
}
func GetAllUser() (users []*table.User, err error) {
err = DB().Find(&users).Error
return
}
func UpdateUserNameById(userName string, userId int64) (err error) {
user := new(table.User)
err = DB().Where("id = ?", userId).First(user).Error
if err != nil {
return
}
user.UserName = userName
err = DB().Save(user).Error
return
}
func DeleteUserById(userId int64) (err error) {
user := new(table.User)
err = DB().Where("id = ?", userId).First(user).Error
if err != nil {
return
}
err = DB().Delete(user).Error
return
}
複製代碼
通過上面幾步的設置後咱們就能夠在項目裏使用gorm
訪問數據庫了,因爲咱們項目的main goroutine
中運行了http
服務,因此咱們使用測試用例對上面dao
包中定義的幾個方法進行一下測試。
篇幅緣由我就只貼一個GetAllUsers
方法的測試用例了:
func TestGetAllUser(t *testing.T) {
tests := []struct {
name string
wantErr bool
}{
{
name: "test",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotUsers, err := GetAllUser()
if (err != nil) != tt.wantErr {
t.Errorf("GetAllUser() error = %v, wantErr %v", err, tt.wantErr)
return
}
for _, user := range gotUsers {
log.Info("user: %v", user)
}
})
}
}
複製代碼
運行測試後,能夠看到結果:
INFO user: &{1 2020-02-15 14:14:46 +0800 CST 2020-02-15 06:44:17 +0800 CST}
--- PASS: TestGetAllUsers (0.00s)
--- PASS: TestGetAllUsers/test (0.00s)
PASS
Process finished with exit code 0
複製代碼
關注文末的公衆號回覆gohttp05
能夠獲得完整的測試用例代碼,建議這些CRUD
都要寫好測試用例進行自測,使用GoLand
能夠很容易的生成測試函數和運行測試。
引入ORM
後,咱們項目中的代碼就比較多了,都放在根目錄下的main
包中有點雜亂,因此咱們根據各部分的功能和職責對項目目錄進行了簡單的劃分,劃分後的目錄結構以下:
http_demo
|
└───handler//route handler
|
└───logic//business logic
|
└───middleware
│
└───model
│ └───dao
│ │ init.go
│ └───table
│ │ user.go
└───router// router
|
| main.go
複製代碼
感受今天的內容仍是挺多的,尤爲對於剛入門Go
的同窗們必定要把今天的代碼下載下來實操一遍才能掌握。gorm
提供的功能仍是不少的,每一個功能在官方文檔裏都有講解,咱們這裏就不作過多介紹了。這篇文章的目的主要是讓你們能快速入門,同時把ORM
相關的代碼管理和初始化流程作的規範些,這些組織方式徹底能夠應用到生產級別的項目中的。
關注文末的公衆號回覆
gohttp05
獲取文章中完整的源代碼,喜歡個人文章請點贊和收藏。