百億數據百億花, 庫若恆河沙復沙,Go lang1.18入門精鍊教程,由白丁入鴻儒,Go lang數據庫操作實踐EP12
- 2022 年 8 月 18 日
- 筆記
Golang可以通過Gorm包來操作數據庫,所謂ORM,即Object Relational Mapping(數據關係映射),說白了就是通過模式化的語法來操作數據庫的行對象或者表對象,對比相對靈活繁複的SQL語句,ORM上手簡單,通用性較高,但是在性能層面略有損耗,Gorm的底層是結構體對象,關於結構體,請移玉步至:你有對象類,我有結構體,Go lang1.18入門精鍊教程,由白丁入鴻儒,go lang結構體(struct)的使用EP06。
Gorm的安裝與配置
首先如果要使用Gorm操作數據庫,得先有數據庫才行,這裡為了全平台統一標準,我們使用Docker來安裝Mysql數據庫,Docker的安裝請參見:一寸宕機一寸血,十萬容器十萬兵|Win10/Mac系統下基於Kubernetes(k8s)搭建Gunicorn+Flask高可用Web集群,運行命令運行mysql容器:
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.19
注意這裡如果宿主機已經有Mysql服務了,需要將:左邊的端口號錯開,改成3307或者其他什麼端口。
隨後在終端運行命令安裝Gorm包:
go get -u github.com/jinzhu/gorm
這裡-u參數的意思是為當前用戶安裝,並不局限於某個項目。
隨後安裝Mysql數據庫鏈接驅動包:
go get -u github.com/go-sql-driver/mysql
接着在任意位置編寫test.go腳本:
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
db, err := gorm.Open("mysql", "root:root@(localhost)/mytest?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
fmt.Println(err)
fmt.Println("連接數據庫出錯")
return
}
defer db.Close()
fmt.Println("鏈接Mysql成功")
}
這裡導入輸出包和Gorm包,同時通過下劃線的形式導入mysql驅動包,這樣做的好處是mysql驅動的init()函數會在被導入時執行,因為我們並不需要驅動包的具體模塊或者函數,而僅僅是用它連一下數據庫而已。
隨後,創建結構體變量db,注意Open函數對應的Mysql參數是否正確。
注意,結構體變量賦值過程中如果報錯,需要判斷err變量內容,並且使用return關鍵字提前結束邏輯,關於golang的錯誤處理,可參見:人非聖賢孰能無過,Go lang1.18入門精鍊教程,由白丁入鴻儒,Go lang錯誤處理機制EP11
最後,使用defer關鍵字在所有邏輯執行後關閉Mysql數據庫鏈接。
編譯執行後,程序返回:
鏈接Mysql成功
當然Gorm並不僅僅只能操作Mysql,其他主流數據庫也都支持,比方說Sqllite3,事實上,在成本有限或者緩存體系比較完備的情況下,Sqllite3完全可以替代Mysql,首先安裝sqllite3驅動:
go get -u github.com/jinzhu/gorm/dialects/sqlite
然後修改test.go文件:
package main
import (
"fmt"
"github.com/jinzhu/gorm"
//_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
func main() {
//db, err := gorm.Open("mysql", "root:root@(localhost)/mytest?charset=utf8mb4&parseTime=True&loc=Local")
db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
if err != nil {
fmt.Println(err)
fmt.Println("連接數據庫出錯")
return
}
defer db.Close()
fmt.Println("鏈接sqllite3成功")
}
編譯執行後返回:
鏈接sqllite3成功
數據庫操作
連接好數據庫之後,我們就可以做一些數據庫層面的操作了,比如程序層面的數據庫遷移操作:
// 文章信息
type ArticleInfo struct {
ID uint
Title string
Author string
}
這裡建立文章表的結構體數據,隨後編寫遷移邏輯:
//數據遷移
db.AutoMigrate(&ArticleInfo{})
fmt.Println("表創建成功")
進入Mysql命令行,輸入命令:
MySQL [(none)]> use mytest;
Database changed
MySQL [mytest]> desc article_infos
-> ;
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | YES | | NULL | |
| author | varchar(255) | YES | | NULL | |
+--------+------------------+------+-----+---------+----------------+
3 rows in set (0.03 sec)
MySQL [mytest]>
沒有問題。
創建數據:
a1 := ArticleInfo{1, "iris", "iris"}
a2 := ArticleInfo{2, "iris", "女"}
// 創建記錄
db.Create(&a1)
db.Create(&a2)
這裡我們聲明兩個結構體變量,然後將其指針傳遞給db變量的Create函數,編譯運行後,鍵入命令進行查詢操作:
MySQL [mytest]> select * from article_infos\g
+----+-------+--------+
| id | title | author |
+----+-------+--------+
| 1 | iris | iris |
| 2 | iris | 女 |
+----+-------+--------+
隨後,將剛才入庫的數據查詢出來:
// 查詢
a := new(ArticleInfo)
db.First(a)
fmt.Println(a)
這裡通過new關鍵字初始化結構體,然後使用First函數獲取第一條記錄。
程序返回:
鏈接mysql成功
&{1 iris iris}
查出來的結構體指針可以直接用來做修改操作:
// 查詢
a := new(ArticleInfo)
db.First(a)
fmt.Println(a)
//修改
db.Model(&a).Update("Author", "123")
fmt.Println(a)
程序返回:
鏈接mysql成功
&{1 iris iris}
&{1 iris 123}
非常方便。
最後,是刪除操作:
// 刪除
db.Delete(&a)
這裡通過指針傳入Delete函數即可:
MySQL [mytest]> select * from article_infos\g
+----+-------+--------+
| id | title | author |
+----+-------+--------+
| 2 | iris | 女 |
該條記錄已經被物理刪除。
執行原生SQL
如果我們需要執行原生的sql語句,Gorm也提供了對應的函數:
var articles []ArticleInfo
// 查詢 執行用Scan 和Find 一樣
db = db.Raw("select * from article_infos ").Scan(&articles)
fmt.Println(articles)
這裡只需要聲明文章的結構體變量,然後執行Scan函數即可:
[{2 iris 女} {3 iris iris} {4 iris 女}]
這裡會返回一個切片嵌套結構體的結果集。
除此之外,更新和刪除操作:
// 更新和刪除.插入用 Exec
db = db.Exec("update article_infos set author='123' where id = 2")
fmt.Println("更新了", db.RowsAffected, "條數據")
db = db.Exec("delete from article_infos where id=4")
fmt.Println("更新了", db.RowsAffected, "條數據")
程序返回:
[]main.ArticleInfo更新了 1 條數據
更新了 1 條數據
結語
目前Golang的比較流行的ORM包除了Gorm,還有Xorm,對比Python數據庫ORM的百花齊放,百家爭鳴,Go lang還有很長的一段路需要走,真實環境下的數據庫操作也不僅僅是增刪改查,更多操作請移步Gorm官方文檔://gorm.io/zh_CN/docs/