Go Gorm 示例詳解
1. 概念
Gorm 官網(wǎng):https://gorm.io/zh_CN/docs/
Gorm:The fantastic ORM library for Golang aims to be developer friendly,這是官網(wǎng)的介紹,簡單來說 Gorm 就是一款高性能的 Golang ORM 庫,便于開發(fā)人員提高效率
那么 ORM(Object Relation Mapping) 又是什么呢?在 Golang 語言中,Object指的就是 struct 結(jié)構(gòu)體對象,Relation 就是數(shù)據(jù)庫當(dāng)中的關(guān)系,Mapping則表示兩者具有映射關(guān)系,具體表現(xiàn)如下:
- Go當(dāng)中的結(jié)構(gòu)體聲明 <-> 數(shù)據(jù)庫層面的表結(jié)構(gòu)
- Go當(dāng)中的結(jié)構(gòu)體實例 <-> 數(shù)據(jù)庫層面的一條表記錄
2. 數(shù)據(jù)庫連接
2.1 安裝依賴
想要在 Go 代碼中使用 gorm 我們需要先引入對應(yīng)的依賴:
- gorm 庫依賴:
gorm.io/gorm - 特定數(shù)據(jù)庫驅(qū)動依賴:
gorm.io/driver/mysql
然后使用 go mod 包管理工具加載對應(yīng)的依賴:
go mod init first_gorm:初始化

go mod tidy:加載依賴

然后就可以開始編寫代碼了!
2.2 連接數(shù)據(jù)庫
在操作數(shù)據(jù)庫之前,我們還需要與指定的數(shù)據(jù)庫建立連接,此處以 MySQL數(shù)據(jù)庫為例:
基本語法:db, err := gorm.Open(mysql.Open(dsn語句), &gorm.Config{})
其中 dsn 語句為特定的連接格式,形式如下:user:pwd@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println("數(shù)據(jù)庫連接失敗!", err)
}
fmt.Println(db)
}程序運行結(jié)果:

控制臺打印出 db 對象,說明我們已經(jīng)成功與數(shù)據(jù)庫建立連接(必須保證數(shù)據(jù)庫中存在指定的數(shù)據(jù)庫)
3. 數(shù)據(jù)庫基本操作
3.1 創(chuàng)建表(表關(guān)系映射)
3.1.1 基本使用
我們可以使用 gorm 提供的 API 來創(chuàng)建指定的表,需要關(guān)注的是 結(jié)構(gòu)體聲明 <=> 數(shù)據(jù)庫表結(jié)構(gòu),因此我們想要創(chuàng)建一個表結(jié)構(gòu)實則只需要定義一個結(jié)構(gòu)體類型
-- 創(chuàng)建user表 -- create table t_user ( user_id bigint primary key auto_increment, user_name varchar(32) not null, user_pwd varchar(128) not null, user_phone varchar(32) unique )
使用上述 SQL 語句創(chuàng)建表的行為等價于在 Go 語言當(dāng)中定義下列結(jié)構(gòu)體對象:
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}創(chuàng)建表基本語法:err := db.AutoMigrate(&特定結(jié)構(gòu)體{})
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println("數(shù)據(jù)庫連接失敗!", err)
}
err = db.AutoMigrate(&User{})
if err != nil {
fmt.Println("數(shù)據(jù)庫表遷移失敗!", err)
}
}程序運行結(jié)果:

3.1.2 自定義表名
我們發(fā)現(xiàn)定義結(jié)構(gòu)體名稱為 “User” 時會創(chuàng)建 “users” 的表名,但是如果我就希望叫做 “t_user” 應(yīng)該怎么辦呢?我們可以定義一個名為 TableName的方法接收器,格式如下:
func (*User) TableName() string {
return "t_user"
}刪除原先的表后再次運行,可以發(fā)現(xiàn)此時表名稱已經(jīng)指定為t_user了
3.2 新增記錄
我們還可以使用 gorm 提供的 API 進行表記錄的插入,這里我們需要關(guān)注** 結(jié)構(gòu)體實例 <=> 表記錄** 之間的映射關(guān)系,也就意味著我們可以通過創(chuàng)建一個結(jié)構(gòu)體實例,實現(xiàn)插入一條記錄的效果
3.2.1 單條數(shù)據(jù)插入
基本語法:db.Create(&結(jié)構(gòu)體實例)
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println("數(shù)據(jù)庫連接失敗!", err)
}
// 插入單條數(shù)據(jù)
var user = User{UserName: "wjj", UserPwd: "123", UserPhone: "111"}
db.Create(&user)
// 再次打印user
fmt.Println(user)
}數(shù)據(jù)庫表結(jié)果:

程序運行結(jié)果:

?? 提示:從中我們還可以發(fā)現(xiàn),插入數(shù)據(jù)之后,還會將數(shù)據(jù)庫表中記錄回顯到結(jié)構(gòu)體實例當(dāng)中!這也是為什么需要傳遞地址的原因!
3.2.2 批量插入數(shù)據(jù)
當(dāng)我們需要批量插入多條數(shù)據(jù)的時候,循環(huán)調(diào)用 db.Create(&結(jié)構(gòu)體實例)這個方法效率就太低了!因為數(shù)據(jù)庫連接會話頻繁創(chuàng)建銷毀耗時比較高,更合適的方法就是進行批量插入
基本語法:db.Create(&結(jié)構(gòu)體實例切片),仍舊是 Create 函數(shù),但是參數(shù)我們可以傳遞結(jié)構(gòu)體實例切片
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 批量插入多條數(shù)據(jù)
var users = []User{
{UserName: "th", UserPwd: "123", UserPhone: "222"},
{UserName: "lhf", UserPwd: "123", UserPhone: "333"},
{UserName: "zcy", UserPwd: "123", UserPhone: "444"},
}
db.Create(&users)
// 打印結(jié)果
fmt.Println(users)
}數(shù)據(jù)庫表結(jié)果:

程序運行結(jié)果:

3.3 查詢記錄
3.3.1 查詢所有記錄
基本語法:db.Find(&結(jié)構(gòu)體實例切片)
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 查詢?nèi)坑涗?
var users []User
db.Find(&users)
// 打印結(jié)果
fmt.Println(users)
}程序運行結(jié)果:

3.3.2 按照條件查詢
我們可以使用 Where 指定查詢條件進行過濾
基本語法:db.Where("user_id > ?", 2).Find()表示想要查詢 user_id > 2 的所有記錄
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 按照條件查詢
var users []User
db.Where("user_id > ?", 2).Find(&users)
// 打印
fmt.Println(users)
}程序運行結(jié)果:

3.3.3 查詢單條記錄
查詢單條記錄有以下兩種情況:
- 查詢第一條記錄:
db.First(&結(jié)構(gòu)體實例) - ???????查詢最后一條記錄:
db.Last(&結(jié)構(gòu)體實例)
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 查詢第一條記錄
var firstUser User
db.First(&firstUser)
// 查詢最后一條記錄
var lastUser User
db.Last(&lastUser)
fmt.Println(firstUser, lastUser)
}程序運行結(jié)果:

3.3.4 查詢記錄總數(shù)
基本語法:db.Find(&結(jié)構(gòu)體實例切片).Count(&整型變量)
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 查詢總數(shù)
var users []User
var totalSize int64
db.Find(&users).Count(&totalSize)
fmt.Println("記錄總數(shù):", totalSize)
}程序運行結(jié)果:

3.4 修改記錄
3.4.1 按照默認(rèn)主鍵修改
基本語法:db.Save(&結(jié)構(gòu)體實例)會按照結(jié)構(gòu)體實例當(dāng)中的主鍵字段找到對應(yīng)數(shù)據(jù)庫記錄進行修改
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 查詢user_id為1的記錄
var stu User
db.Where("user_id = ?", 1).Find(&stu)
// 修改stu姓名為wjj1
stu.UserName = "wjj1"
// 修改(按照主鍵修改)
db.Save(&stu)
}程序運行結(jié)果:

3.4.2 修改指定字段
上述按照默認(rèn)主鍵修改的方式修改了全部字段,如果我們只想修改特定單個字段可以使用以下方式:
基本語法:db.Model(&結(jié)構(gòu)體實例).Where(條件).Update(字段, 修改值)
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 修改user_id為1的記錄 user_name為wjj
var stu User
db.Model(&stu).Where("user_id = ?", 1).Update("user_name", "wjj")
}程序運行結(jié)果:

3.4.3 修改多個字段
我們還可以指定多個字段進行修改
基本語法:db.Model(&結(jié)構(gòu)體實例).Where(條件).updates(修改實例),其中修改實例可以是結(jié)構(gòu)體也可以是map對象
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 修改user_id為1的記錄 user_name為WJJ, user_pwd為"999"
var stu User
var fields = map[string]interface{}{"user_name": "WJJ", "user_pwd": "999"}
db.Model(&stu).Where("user_id = ?", 1).Updates(fields)
}程序運行結(jié)果:

3.5 刪除記錄
3.5.1 按照默認(rèn)主鍵刪除
基本語法:db.Delete(&結(jié)構(gòu)體實例)會自動按照主鍵找到表中記錄,然后刪除
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 按照默認(rèn)主鍵刪除
var user = User{UserId: 1}
db.Delete(&user)
}程序運行結(jié)果:

3.5.2 指定條件刪除
我們想更加精細(xì)化的控制刪除條件就需要借助 Where 函數(shù):
基本語法:db.Where(條件).Delete(&結(jié)構(gòu)體實例)
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// User 結(jié)構(gòu)體聲明
type User struct {
UserId int64 `gorm:"primaryKey;autoIncrement"`
UserName string `gorm:"not null;type:varchar(32)"`
UserPwd string `gorm:"not null;type:varchar(128)"`
UserPhone string `gorm:"unique;type:varchar(32)"`
}
func (*User) TableName() string {
return "t_user"
}
func main() {
// 連接數(shù)據(jù)庫
var dsn = "root:QWEzxc123456@tcp(127.0.0.1:3306)/gorm_test"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 按照條件刪除
db.Where("user_id = ?", 10).Delete(&User{})
}程序運行結(jié)果:

到此這篇關(guān)于Go Gorm 詳解的文章就介紹到這了,更多相關(guān)Go Gorm 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言使用net/http實現(xiàn)簡單登錄驗證和文件上傳功能
這篇文章主要介紹了Go語言使用net/http實現(xiàn)簡單登錄驗證和文件上傳功能,使用net/http模塊編寫了一個簡單的登錄驗證和文件上傳的功能,在此做個簡單記錄,需要的朋友可以參考下2023-07-07
Go語言使用漏桶算法和令牌桶算法來實現(xiàn)API限流
為防止服務(wù)器被過多的請求壓垮,限流是一個至關(guān)重要的技術(shù)手段,下面我們就來看看如何使用漏桶算法和令牌桶算法來實現(xiàn) API 的限流吧2024-11-11
利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞
這篇文章主要介紹了利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Go語言中實現(xiàn)打印堆棧的errors包的用法詳解
因為Go語言提供的錯誤太簡單了,以至于簡單的我們無法更好的處理問題,所以誕生了很多對錯誤處理的庫,github.com/pkg/errors是比較簡潔的一樣,本文就來聊聊它的具體用法吧2023-07-07
使用Go語言實現(xiàn)xmind文件轉(zhuǎn)換為markdown
這篇文章主要來和大家一起深入探討如何用Go語言構(gòu)建一個強大的命令行工具,實現(xiàn)XMind到Markdown的無損轉(zhuǎn)換,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-06-06

