链接:https://gorm.io/zh_CN/docs/connecting_to_the_database.html
快速入门
使用gorm之前必须要建立一个数据库。gorm只能操作表。
导入gorm包的时候要导入mysql包,因为MySQL包导入时init函数自动运行驱动。
package main
import (
"database/sql"
"log"
"os"
"time"
"gorm.io/driver/mysql"//源码的init函数会执行MySQL驱动
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code sql.NullString
Price uint
}
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
//sql才是最重要的,本着这个原则我尽量的给大家看到每个api背后的sql语句是什么
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式,提前建立数据库gorm_test
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
//定义一个表结构, 将表结构直接生成对应的表 - migrations
// 迁移 schema
_ = db.AutoMigrate(&Product{}) //此处应该有sql语句
// 新增
db.Create(&Product{Code: sql.NullString{"D42", true}, Price: 100})
// Read
var product Product
db.First(&product, 1) // 根据整形主键查找
db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录
// Update - 将 product 的 price 更新为 200
db.Model(&product).Update("Price", 200)
// Update - 更新多个字段
db.Model(&product).Updates(Product{Price: 200, Code:sql.NullString{"", true}}) // 仅更新非零值字段
//如果我们去更新一个product 只设置了price:200
//db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
// Delete - 删除 product, 并没有执行delete语句,逻辑删除
db.Delete(&product, 1)
}
没放logger之前
package main
import (
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type User struct {
UserID uint `gorm:"primarykey"`
Name string `gorm:"column:user_name;type:varchar(50);index:idx_user_name;unique;default:'bobby'"`
}
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
_ = db.AutoMigrate(&User{}) //此处应该有sql语句
db.Create(&User{})
}
通过creat插入记录
package main
import (
"database/sql"
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
a := []int{1,2,3}
b := a[:]
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
_ = db.AutoMigrate(&User{}) //此处应该有sql语句
user := User{
Name : "bobby2",
}
fmt.Println(user.ID)
result := db.Create(&user)
fmt.Println(user.ID) // 返回插入数据的主键
fmt.Println(result.Error) // 返回 error
fmt.Println(result.RowsAffected) // 返回插入记录的条数
//db.Model(&User{ID:1}).Update("Name", "")
//updates语句不会更新零值,但是update语句会更新
//empty := ""
//db.Model(&User{ID:1}).Updates(User{Email: &empty})
//解决仅更新非零值字段的方法有两种
/*
1. 将string 设置为 *string
2. 使用sql的NULLxxx来解决
*/
}
package main
import (
"database/sql"
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
//单一的 SQL 语句
var users = []User{{Name: "bobby1"}, {Name: "bobby2"}, {Name: "bobby3"}}
//db.Create(&users)
//为什么不一次性提交所有的 还要分批次,因为sql语句有长度限制
db.CreateInBatches(users, 10000)//这里的10000指的是一次提交10000个sql语句
for _, user := range users {
fmt.Println(user.ID) // 1,2,3
}
db.Model(&User{}).Create(map[string]interface{}{
"Name": "jinzhu", "Age": 18,
})
}
package main
import (
"database/sql"
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
//通过first查询单个数据, 获取第一条记录(主键升序)
//var user User
//db.First(&user)
//通过主键查询
//我们不能给user赋值
//result := db.First(&user, []int{1,2,3})
//if errors.Is(result.Error, gorm.ErrRecordNotFound){
// fmt.Println("未找到")
//}
//fmt.Println(user.ID)
//检索全部对象
var users []User
result := db.Find(&users)
fmt.Println("总共记录:", result.RowsAffected)
for _, user := range users{
fmt.Println(user.ID)
}
}
package main
import (
"database/sql"
"fmt"
"log"
"math/rand"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type User struct {
ID uint
MyName string `gorm:"column:name"`
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
type BaseModel struct {
ID int32 `gorm:"primarykey;type:int" json:"id"` //为什么使用int32, bigint
CreatedAt time.Time `gorm:"column:add_time" json:"-"`
UpdatedAt time.Time `gorm:"column:update_time" json:"-"`
DeletedAt gorm.DeletedAt `json:"-"`
IsDeleted bool `json:"-"`
}
type OrderInfo struct{
BaseModel
User int32 `gorm:"type:int;index"`
OrderSn string `gorm:"type:varchar(30);index"` //订单号,我们平台自己生成的订单号
PayType string `gorm:"type:varchar(20) comment 'alipay(支付宝), wechat(微信)'"`
//status大家可以考虑使用iota来做
Status string `gorm:"type:varchar(20) comment 'PAYING(待支付), TRADE_SUCCESS(成功), TRADE_CLOSED(超时关闭), WAIT_BUYER_PAY(交易创建), TRADE_FINISHED(交易结束)'"`
TradeNo string `gorm:"type:varchar(100) comment '交易号'"` //交易号就是支付宝的订单号 查账
OrderMount float32
PayTime *time.Time `gorm:"type:datetime"`
Address string `gorm:"type:varchar(100)"`
SignerName string `gorm:"type:varchar(20)"`
SingerMobile string `gorm:"type:varchar(11)"`
Post string `gorm:"type:varchar(20)"`
}
type OrderGoods struct{
BaseModel
Order int32 `gorm:"type:int;index"`
Goods int32 `gorm:"type:int;index"`
//把商品的信息保存下来了 , 字段冗余, 高并发系统中我们一般都不会遵循三范式 做镜像 记录
GoodsName string `gorm:"type:varchar(100);index"`
GoodsImage string `gorm:"type:varchar(200)"`
GoodsPrice float32
Nums int32 `gorm:"type:int"`
}
func GenerateOrderSn(userId int32) string{
//订单号的生成规则
/*
年月日时分秒+用户id+2位随机数
*/
now := time.Now()
rand.Seed(time.Now().UnixNano())
orderSn := fmt.Sprintf("%d%d%d%d%d%d%d%d",
now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Nanosecond(),
userId, rand.Intn(90)+10,
)
return orderSn
}
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
//通过where查询
//var user User
//var users []User
//db.Where("name = ?", "bobby").First(&user)
//db.Where(&User{MyName:"bobby"}).First(&user)
//db.Where(&User{MyName:"bobby1", Age: 0}).Find(&users)
//db.Where(map[string]interface{}{"name": "bobby", "age":0}).Find(&users)
//for _, user := range users{
// fmt.Println(user.ID)
//}
_ = db.AutoMigrate(OrderInfo{}, OrderGoods{})
tx := db.Begin()
order := OrderInfo{
OrderSn: GenerateOrderSn(1),
OrderMount: 44.2,
Address: "北京市",
SignerName: "bobby",
SingerMobile: "18787878787",
Post: "请尽快发货",
}
if result := tx.Save(&order); result.RowsAffected == 0 {
tx.Rollback()
fmt.Println("创建订单失败")
}
var orderGoods []*OrderGoods
orderGoods = append(orderGoods, &OrderGoods{
Order: order.ID,
Goods: 421,
GoodsName: "烟台红富士苹果12个 净重2.6kg以上 单果190-240g 新生鲜水果",
GoodsImage: "https://py-go.oss-cn-beijing.aliyuncs.com/goods_images/df392d01993cdab9de740fe17798bda1",
GoodsPrice: 44.9,
Nums: 1,
})
for _, orderGood := range orderGoods {
orderGood.Order = order.ID
}
//批量插入orderGoods
if result := tx.CreateInBatches(orderGoods, 100); result.RowsAffected == 0 {
tx.Rollback()
fmt.Println("创建订单失败")
}
tx.Commit()
//查询方式条件有三种 1. string 2. struct 3. map
}
package main
import (
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
// `User` 属于 `Company`,`CompanyID` 是外键
type User struct {
gorm.Model
Name string
CompanyID int //数据库中存储的字段company_id
Company Company
}
type Company struct {
ID int
Name string
}
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
//db.AutoMigrate(&User{}) //新建了user表和company表,并设置了外键
//db.Create(&User{
// Name: "bobby",
// Company: Company{
// Name:"慕课网",
// },
//})
db.Create(&User{
Name: "bobby2",
Company: Company{
ID:1,
},
})
}
package main
import (
"database/sql"
"gorm.io/gorm/schema"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Language struct {
gorm.Model
Name string
AddTime sql.NullTime //每个记录创建的时候自动加上当前时间加入到AddTime中
}
//func (l *Language) BeforeCreate(tx *gorm.DB) (err error){
// l.AddTime = time.Now()
// return
//}
//在gorm中可以通过给某一个struct添加TableName方法来自定义表名
func (Language) TableName() string{
return "my_language"
}
/*
1. 我们自己定义表名是什么
2. 统一的给所有的表名加上一个前缀
*/
func main() {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:root@tcp(192.168.0.104:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // Log level
Colorful: true, // 禁用彩色打印
},
)
// 全局模式
//NamingStrategy和Tablename不能同时配置,
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy:schema.NamingStrategy{//配置表名前缀
TablePrefix: "mxshop_",
},
Logger: newLogger,
})
if err != nil {
panic(err)
}
db.AutoMigrate(&Language{})
db.Create(&Language{
Name:"python",
})
}