package main

import (
    "fmt"
    "strconv"
    "time"

    _ "github.com/go-sql-driver/mysql"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

//定义一个结构体,gorm允许定义结构体的时候通过tag定义结构体的权限,例如:
// type User struct {
//     Name string `gorm:"<-:create"` // 允许读和创建
//     Name string `gorm:"<-:update"` // 允许读和更新
//     Name string `gorm:"<-"`        // 允许读和写(创建和更新)
//     Name string `gorm:"<-:false"`  // 允许读,禁止写
//     Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)
//     Name string `gorm:"->;<-:create"` // 允许读和写
//     Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
//     Name string `gorm:"-"`  // 通过 struct 读写会忽略该字段
//   }

// 定义一个雇员
type Emp struct {
    Id         int
    Name       string
    Age        int
    Gender     uint8     // 对应数据库中的bit
    Birthday   time.Time // 对应数据库中的date
    Salary     float32
    Department string
}

// 定义一个学生
type Student struct {
    Name string
    Age  int
}

// 实例化结构体的时候,time.Time输入字符串报错,所以这里定义了一个将字符串转换成时间的函数
func s2t(s string) time.Time {
    t, _ := time.Parse("2006-01-02", s)
    return t
}

func main() {
    dsn := "root:123456@(127.0.0.1:3306)/golang?charset=utf8mb4&parseTime=true"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        fmt.Printf("connect DB failed, err:%v\n", err)
        return
    }

    // 单个插入
    employee := Emp{
        Name:       "WangWu1",
        Age:        18,
        Gender:     1,
        Birthday:   s2t("1995-12-12"),
        Salary:     31232.123,
        Department: "销售部",
    }
    user := Student{Name: "zhaosi", Age: 33}
    result := db.Create(&employee)
    fmt.Println(employee.Id)         // 返回插入数据的主键
    fmt.Println(result.Error)        // 返回 error
    fmt.Println(result.RowsAffected) // 返回插入记录的条数
    result := db.Select("Name", "Age").Create(&user)
    fmt.Println(result.Error)        // 返回 error
    fmt.Println(result.RowsAffected) // 返回插入记录的条数
    fmt.Println(employee)

    // 批量插入
    stu := []Student{
        {Name: "stu1", Age: 18},
        {Name: "stu2", Age: 19},
        {Name: "stu3", Age: 11},
        {Name: "stu4", Age: 12},
        {Name: "stu5", Age: 13},
    }

    result := db.Create(&stu)
    fmt.Println(result.Error)        // nil
    fmt.Println(result.RowsAffected) // 5

    // 批量分配插入
    stu1 := make([]Student, 0)
    for i := 100; i < 200; i++ {

        stu1 = append(stu1, Student{Name: "stu" + strconv.Itoa(i), Age: 20 + i})
    }
    ret := db.CreateInBatches(stu1, 10) // 每次写入10个
    fmt.Println(ret.Error)              // nil
    fmt.Println(ret.RowsAffected)       // 100

    // GORM 支持根据 map[string]interface{} 和 []map[string]interface{}{} 创建记录
    ret := db.Model(&Student{}).Create(stu1) // 基于元素为map类型的切片创建
    fmt.Println(ret.Error)                   // nil
    fmt.Println(ret.RowsAffected)            // 100

}