Golang学习之GORM框架
程序员文章站
2022-07-03 23:18:47
...
基础
程序
package main
import "github.com/gin-gonic/gin"
func sayHello(c *gin.Context) {
c.JSON(200, gin.H{
"message": "hello golang",
})
}
func main() {
r := gin.Default()
r.GET("/hello", sayHello)
// 启动
_ = r.Run()
}
模板渲染
func sayHello(w http.ResponseWriter, r *http.Request) {
// 解析模板
t, err := template.ParseFiles("./hello.tmpl")
if err != nil {
fmt.Printf("Parse template failed, err:%v\n", err)
return
}
// 渲染模板
name := "五月"
err1 := t.Execute(w, name)
if err1 != nil {
fmt.Printf("render template failed, err:%v", err)
return
}
}
func main() {
http.HandleFunc("/", sayHello)
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err:%v", err)
return
}
}
JSON渲染
func main() {
r := gin.Default()
// gin.H 是map[string]interface{}的缩写
r.GET("/someJSON", func(c *gin.Context) {
// 方式一:自己拼接JSON
c.JSON(http.StatusOK, gin.H{"message": "Hello world!"})
})
r.GET("/moreJSON", func(c *gin.Context) {
// 方法二:使用结构体
var msg struct {
Name string `json:"user"`
Message string
Age int
}
msg.Name = "小王子"
msg.Message = "Hello world!"
msg.Age = 18
c.JSON(http.StatusOK, msg)
})
r.Run(":8080")
}
XML渲染
func main() {
r := gin.Default()
// gin.H 是map[string]interface{}的缩写
r.GET("/someXML", func(c *gin.Context) {
// 方式一:自己拼接JSON
c.XML(http.StatusOK, gin.H{"message": "Hello world!"})
})
r.GET("/moreXML", func(c *gin.Context) {
// 方法二:使用结构体
type MessageRecord struct {
Name string
Message string
Age int
}
var msg MessageRecord
msg.Name = "小王子"
msg.Message = "Hello world!"
msg.Age = 18
c.XML(http.StatusOK, msg)
})
r.Run(":8080")
}
获取querystring值
func main() {
r := gin.Default()
r.GET("/querystring", func(c *gin.Context) {
// 第一个参数为要检索的值, 第二个参数为检索不到默认设置的值
userName := c.DefaultQuery("username", "May")
address := c.Query("address")
c.JSON(http.StatusOK, gin.H{
"UserName": userName,
"Address": address,
})
})
r.Run(":9000")
}
获取form参数
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.POST("/user/search", func(c *gin.Context) {
// DefaultPostForm取不到值时会返回指定的默认值
//username := c.DefaultPostForm("username", "小王子")
username := c.PostForm("username")
address := c.PostForm("address")
//输出json结果给调用方
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"username": username,
"address": address,
})
})
r.Run(":8080")
}
获取path参数
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/search/:username/:address", func(c *gin.Context) {
username := c.Param("username")
address := c.Param("address")
//输出json结果给调用方
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"username": username,
"address": address,
})
})
r.Run(":8080")
}
参数绑定
// Binding from JSON
type Login struct {
User string `form:"user" json:"user" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
}
func main() {
router := gin.Default()
// 绑定JSON的示例 ({"user": "q1mi", "password": "123456"})
router.POST("/loginJSON", func(c *gin.Context) {
var login Login
if err := c.ShouldBind(&login); err == nil {
fmt.Printf("login info:%#v\n", login)
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
// 绑定form表单示例 (user=q1mi&password=123456)
router.POST("/loginForm", func(c *gin.Context) {
var login Login
// ShouldBind()会根据请求的Content-Type自行选择绑定器
if err := c.ShouldBind(&login); err == nil {
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
// 绑定QueryString示例 (/loginQuery?user=q1mi&password=123456)
router.GET("/loginForm", func(c *gin.Context) {
var login Login
// ShouldBind()会根据请求的Content-Type自行选择绑定器
if err := c.ShouldBind(&login); err == nil {
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
路由重定向
路由重定向,使用HandleContext
:
r.GET("/test", func(c *gin.Context) {
// 指定重定向的URL
c.Request.URL.Path = "/test2"
r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"hello": "world"})
})
gorm
使用GORM连接上面的db1
进行创建、查询、更新、删除操作。
func main() {
db, err := gorm.Open("mysql", "root:[email protected](localhost)/gorm?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
// 自动迁移(会在数据库中创建对应的表)
db.AutoMigrate(&entity.UserInfo{})
u1 := entity.UserInfo{1, "七米", "男", "篮球"}
u2 := entity.UserInfo{2, "沙河娜扎", "女", "足球"}
// 创建记录
db.Create(&u1)
db.Create(&u2)
// 查询
var u = new(entity.UserInfo)
db.First(u)
fmt.Printf("%#v\n", u)
var uu entity.UserInfo
db.Find(&uu, "hobby=?", "足球")
fmt.Printf("%#v\n", uu)
// 更新
db.Model(&u).Update("hobby", "双色球")
// 删除
db.Delete(&u)
}
结构体标志
结构体标记(Tag) | 描述 |
---|---|
Column | 指定列名 |
Type | 指定列数据类型 |
Size | 指定列大小, 默认值255 |
PRIMARY_KEY | 将列指定为主键 |
UNIQUE | 将列指定为唯一 |
DEFAULT | 指定列默认值 |
PRECISION | 指定列精度 |
NOT NULL | 将列指定为非 NULL |
AUTO_INCREMENT | 指定列是否为自增类型 |
INDEX | 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引 |
UNIQUE_INDEX | 和 INDEX 类似,只不过创建的是唯一索引 |
EMBEDDED | 将结构设置为嵌入 |
EMBEDDED_PREFIX | 设置嵌入结构的前缀 |
- | 忽略此字段 |
查询
// 根据主键查询第一条记录
db.First(&user)
SELECT * FROM users ORDER BY id LIMIT 1;
// 随机获取一条记录
db.Take(&user)
SELECT * FROM users LIMIT 1;
// 根据主键查询最后一条记录
db.Last(&user)
SELECT * FROM users ORDER BY id DESC LIMIT 1;
// 查询所有的记录
db.Find(&users)
SELECT * FROM users;
// 查询指定的某条记录(仅当主键为整型时可用)
db.First(&user, 10)
SELECT * FROM users WHERE id = 10;
where条件查询
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
SELECT * FROM users WHERE name = 'jinzhu' limit 1;
// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
SELECT * FROM users WHERE name = 'jinzhu';
// <>
db.Where("name <> ?", "jinzhu").Find(&users)
SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
SELECT * FROM users WHERE name in ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
Struct & Map查询
// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
// 主键的切片
db.Where([]int64{20, 21, 22}).Find(&users)
SELECT * FROM users WHERE id IN (20, 21, 22);
注意
当结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0,’ ’,false,或者其他零值,将不会被用于构建查询条件
删除
删除记录
// 删除现有记录
db.Delete(&email)
DELETE from emails where id=10;
// 为删除 SQL 添加额外的 SQL 操作
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
批量删除
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
DELETE from emails where email LIKE "%jinzhu%";
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
DELETE from emails where email LIKE "%jinzhu%"
软删除
如果一个 model 有 DeletedAt
字段,他将自动获得软删除的功能! 当调用 Delete
方法时, 记录不会真正的从数据库中被删除, 只会将DeletedAt
字段的值会被设置为当前时间
db.Delete(&user)
UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
// 批量删除
db.Where("age = ?", 20).Delete(&User{})
UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
// 查询记录时会忽略被软删除的记录
db.Where("age = 20").Find(&user)
SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
// Unscoped 方法可以查询被软删除的记录
db.Unscoped().Where("age = 20").Find(&users)
SELECT * FROM users WHERE age = 20;
物理删除
// Unscoped 方法可以物理删除记录
db.Unscoped().Delete(&order)
DELETE FROM orders WHERE id=10;
更新
更新所有字段
db.First(&user)
user.Name = "七米"
user.Age = 99
db.Save(&user)
UPDATE `users` SET `created_at` = '2020-02-16 12:52:20', `updated_at` = '2020-02-16 12:54:55', `deleted_at` = NULL, `name` = '七米', `age` = 99, `active` = true WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = 1
更新修改字段
// 更新单个属性,如果它有变化
db.Model(&user).Update("name", "hello")
UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
// 根据给定的条件更新单个属性
db.Model(&user).Where("active = ?", true).Update("name", "hello")
UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;
// 使用 map 更新多个属性,只会更新其中有变化的属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})
UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// 警告:当使用 struct 更新时,GORM只会更新那些非零值的字段
// 对于下面的操作,不会发生任何更新,"", 0, false 都是其类型的零值
db.Model(&user).Updates(User{Name: "", Age: 0, Active: false})
更新选定字段
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
上一篇: Golang学习笔记-Iris框架
下一篇: 国际化资源文件配置