这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记
快速上手
import (
"database/sql"
"encoding/json"
"fmt"
_ "github.com/go-sql-driver/mysql"
"os"
)
type User struct {
User_id uint `json:"user_id"`
User_name string `json:"user_name"`
User_password string `json:"user_password"`
}
func main() {
db, err := sql.Open("mysql", "root:qzzx91112@tcp(127.0.0.1:3306)/douyin")
rows, err := db.Query("select * from `user` where `user_name` = ?", "chz")//自带防止sql注入
if err != nil {
fmt.Fprintf(os.Stdout, "%v", err)
}
defer rows.Close() //再结束时关闭,rows相当于游标
var users []User
for rows.Next() {
var user User
err := rows.Scan(&user.User_id, &user.User_name, &user.User_password)
if err != nil {
panic(err)
}
users = append(users, user)
}
for _, user := range users {
user_json, err := json.Marshal(user)
if err != nil {
panic(err)
}
err = json.Unmarshal(user_json, &user)//第二个参数需要以指针格式传输
if err != nil {
panic(err)
}
fmt.Printf("%v", user)
}
}
执行过程
-
连接数据库
使用
sql.Open(driverName,dataSourceName)driverName:数据库名dataSourceName:DSN格式为username:password@protocol(address)/dbname?param=value
连接时会从
drivers中找到对于数据库的驱动,然后执行OpenConnector(DSN)解析DSN并加载到db中。
使用`mysql.NewConnector(mysql.Config{})`连接数据库
```
connector, err := mysql.NewConnector(&mysql.Config{
User: "user",
Passwd: "pasword",
Net: "protocol",
Addr: "address",
DBName: "databasename",
ParseTime: true,
})
```
-
数据操作(CRUD)
func CRUD(){ rows, err := db.Query("select * from `user` where `user_name` = ?", "陈鹤中") if err != nil { fmt.Fprintf(os.Stdout, "%v\n", err) } defer rows.Close() //再结束时关闭,rows相当于游标 var users []User for rows.Next() { var user User err := rows.Scan(&user.User_id, &user.User_name, &user.User_password) if err != nil { panic(err) } users = append(users, user) } r, _ := db.Exec("delete from `user` where `user_name`=?", "test"+strconv.Itoa(i)) id, _ := r.RowsAffected() fmt.Println("\ndelete succ:", id) r, _ := db.Exec("insert into `user` values (null,?,?)", "test"+strconv.Itoa(i), "test_pwd") id, _ := r.LastInsertId() fmt.Println("\ninsert succ:", id) r, _ := db.Exec("update `user` set `user_password`=? where `user_name`=?", "password", "test"+strconv.Itoa(i)) ar, _ := r.RowsAffected() fmt.Println("\nupdate succ:", ar) }事务操作
DB.Begin()开启事务DB.Commit()提交事务DB.Rollback()事务回滚
func (){ conn, _ := db.Begin() for i := 0; i < 10; i++ { r, err := db.Exec("insert into `user` values (null,?,?)", "test"+strconv.Itoa(i), "test_pwd") if err != nil{ conn.Rollback() break } id, _ := r.LastInsertId() fmt.Println("\ninsert succ:", id) } conn.Commit() }
使用gorm操作数据库
Why gorm?
- 全特性 ORM (几乎包含所有特性)
- 模型关联 (一对一, 一对多,一对多(反向), 多对多, 多态关联)
- 钩子 (Before/After Create/Save/Update/Delete/Find)
- 预加载
- 事务
- 复合主键
- SQL 构造器
- 自动迁移
- 日志
- 基于GORM回调编写可扩展插件
- 全特性测试覆盖
- 开发者友好
gorm安装
go get -u github.com/jinzhu/gorm
使用gorm实现CRUD
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
//使用gorm时,结构体的首字母要大写
type User struct {
gorm.Model
User_name string
User_password string
}
func main() {
db, err := gorm.Open(mysql.Open("root:qzzx91112@tcp(127.0.0.1:3306)/douyin_utf8?parseTime=True"))
//在mysql中的日期时间字段时string类型,如果转到`timeTime`类型,需要在代码中用`time.Parse`进行转化
if err != nil {
panic("failed to connect database")
}
//操作数据库
db.AutoMigrate(&User{})
//db.Migrator().CreateTable(&User{}) //创建表
myuser := User{
User_name: "myusername",
User_password: "mypassword",
}
// 增
db.Create(&myuser)
users := make([]User, 3)
for i := 0; i < 2; i++ {
users[i] = User{
User_name: "myusername",
User_password: "mypassword",
}
}
//db.Where("user_name = ?", "myusernname").First(&users) 查询多条数据
fmt.Printf("User:%v is created\n", myuser)
// 查
var user User
db.First(&user, "user_name = ?", "myusername")
fmt.Printf("User:%v is selected\n", user)
// 改
db.Model(&user).Update("user_password", "new_password")
fmt.Printf("User:%v is update to latest\n", user)
// 删 -
db.Delete(&user)
fmt.Println("User is deleted", user)
}
Gorm标签
例:
type User struct {
gorm.Model
Name string
Age sql.NullInt64
Birthday *time.Time
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` //设置字段的大小为255个字节
MemberNumber *string `gorm:"unique;not null"` // 设置 memberNumber 字段唯一且不为空
Num int `gorm:"AUTO_INCREMENT"` // 设置 Num字段自增
Address string `gorm:"index:addr"` // 给Address 创建一个名字是 `addr`的索引
IgnoreMe int `gorm:"-"` //忽略这个字段
}
| 标签 | 说明 |
|---|---|
| Column | 指定列的名称 |
| Type | 指定列的类型 |
| Size | 指定列的大小,默认是 255 |
| PRIMARY_KEY | 指定一个列作为主键 |
| UNIQUE | 指定一个唯一的列 |
| DEFAULT | 指定一个列的默认值 |
| PRECISION | 指定列的数据的精度 |
| NOT NULL | 指定列的数据不为空 |
| AUTO_INCREMENT | 指定一个列的数据是否自增 |
| INDEX | 创建带或不带名称的索引,同名创建复合索引 |
| UNIQUE_INDEX | 类似 索引,创建一个唯一的索引 |
| EMBEDDED | 将 struct 设置为 embedded |
| EMBEDDED_PREFIX | 设置嵌入式结构的前缀名称 |
| - | 忽略这些字段 |
| 标签 | 说明 |
|---|---|
| MANY2MANY | 指定连接表名称 |
| FOREIGNKEY | 指定外键 |
| ASSOCIATION_FOREIGNKEY | 指定关联外键 |
| POLYMORPHIC | 指定多态类型 |
| POLYMORPHIC_VALUE | 指定多态的值 |
| JOINTABLE_FOREIGNKEY | 指定连接表的外键 |
| ASSOCIATION_JOINTABLE_FOREIGNKEY | 指定连接表的关联外键 |
| SAVE_ASSOCIATIONS | 是否自动保存关联 |
| ASSOCIATION_AUTOUPDATE | 是否自动更新关联 |
| ASSOCIATION_AUTOCREATE | 是否自动创建关联 |
| ASSOCIATION_SAVE_REFERENCE | 是否引用自动保存的关联 |
| PRELOAD | 是否自动预加载关联 |