package gormExample import ( "context" "database/sql" "fmt" "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/schema" "log" "reflect" "strings" "time" ) type Post struct{ gorm.Model } type Category struct{ gorm.Model } type PostCategory struct{ gorm.Model } type Box struct{ gorm.Model } func (Box) TableName() string { return "my_box" } type TypeMap struct { gorm.Model FInt int FUInt uint FFloat32 float32 FFloat64 float64 FString string FTime time.Time FByteSlice []byte FIntP *int FUIntP *uint FFloat32P *float32 FFloat64P *float64 FStringP *string FTimeP *time.Time } func Migrate() { if err := DB.Debug().AutoMigrate(&Blog{}, &Service{}, &IAndC{}, &FieldTag{}, &TypeMap{}, &Post{}, &Category{}, &PostCategory{}, &Box{}); err != nil { log.Fatal(err) } } func PointerDiff() { // 模型的零值 typeMap := &TypeMap{} fmt.Printf("%+v\n", typeMap) fmt.Println("=================================") // 查询数据NULL对应的值 DB.First(typeMap, 1) fmt.Printf("%+v\n", typeMap) } type CustomTypeModel struct { gorm.Model FTime time.Time FNullTime sql.NullTime FString string FNullString sql.NullString FUUID uuid.UUID FNullUUID uuid.NullUUID } func CustomType() { //id := uuid.UUID{} //id.Scan() // Scanner //id.Value() // Valuer // 初始化模型 ctm := &CustomTypeModel{} // 迁移数据表 DB.AutoMigrate(ctm) // 创建 ctm.FTime = time.Now() // 当前时间 ctm.FNullTime = sql.NullTime{} // 零值,Valid默认为false ctm.FString = "" ctm.FNullString = sql.NullString{} ctm.FUUID = uuid.New() ctm.FNullUUID = uuid.NullUUID{} DB.Create(ctm) // 查询 DB.First(ctm, ctm.ID) // 判定字段是否为NULL if ctm.FString == "" { fmt.Println("FString is NULL") } else { fmt.Println("FString is NOT NULL") } if ctm.FNullString.Valid == false { fmt.Println("FNullString is NULL") } else { fmt.Println("FNullString is NOT NULL") } } type FieldTag struct { //Field string `gorm:"" json:"" bson:"" xml:""` // Tag gorm.Model // string 类型的处理 FStringDefault string `gorm:""` FTypeChar string `gorm:"type:char(32)"` FTypeVarchar string `gorm:"type:varchar(255)"` FTypeText string `gorm:"type:text"` FTypeBlob []byte `gorm:"type:blob"` FTypeEnum string `gorm:"type:enum('Go', 'GORM', 'MySQL')"` FTypeSet string `gorm:"type:set('Go', 'GORM', 'MySQL')"` FColNum string `gorm:"column:custom_column_name"` // 默认是NULl FColNotNull string `gorm:"type:varchar(255);not null;"` FColDefault string `gorm:"type:varchar(255);not null;default:gorm middle ware;"` FColComment string `gorm:"type:varchar(255);comment:带有注释的字段"` } type IAndC struct { // 基础索引类型 ID uint `gorm:"primaryKey"` Email string `gorm:"type:varchar(255);uniqueIndex"` // unique Age uint8 `gorm:"index;check:age >= 18 AND email is not null"` // 复合索引 FirstName string `gorm:"index:name"` LastName string `gorm:"index:name"` // 顺序关键顺序 // 默认的 priority:10 FirstName1 string `gorm:"index:name1,priority:2"` LastName1 string `gorm:"index:name1,priority:1"` // 索引选项,前缀长度,排序方式,comment Height float32 `gorm:"index:,sort:desc"` AddressHash string `gorm:"index:,length:12,comment:前12个字符作为索引关键字"` } func IAndCCreate() { iac := &IAndC{} iac.Age = 18 if err := DB.Create(iac).Error; err != nil { log.Fatal(err) } fmt.Printf("%+v\n", iac) } type Service struct { gorm.Model //Url string `gorm:"-"` // -:all Url string `gorm:"-:migration; type:varchar(255)"` Schema string Host string `gorm:"<-:false"` Path string `gorm:"<-:update"` QueryString string `gorm:"->:false"` } func ServiceCRUD() { s := &Service{} s.Schema = "http" s.Host = "www.mashibing.com" s.Path = "/" s.Url = "http://www.mashibing.com/" DB.Create(s) } func PaperCrud() { if err := DB.AutoMigrate(&Paper{}); err != nil { log.Fatal(err) } // 常规操作 paper := &Paper{} paper.Subject = "使用Serializer操作Tags字段" paper.Tags = []string{"Go", "Serializer", "Gorm", "MySQL"} // create 会执行序列化工作,serialize if err := DB.Create(paper).Error; err != nil { log.Fatal(err) } // 查询 newPaper := &Paper{} // First会执行反序列化工作,unserialize DB.First(newPaper, 5) fmt.Printf("%+v\n", newPaper) } // 1.定义实现了序列化器接口的类型 type CSVSerializer struct{} // 实现Scan,unserialize时执行 // ctx Context对象 // field 模型的字段对应的类型 // dst 目标值(最终结果赋值到dst) // dbValue 从数据库读取的值 // 错误 func (CSVSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error { // 初始化一个用来存储字段值的变量 var fieldValue []string // 一:解析读取到的数据表的数据 if dbValue != nil { // 不是 NULL // 支持解析的只有string和[]byte // 使用类型检测进行判定 var str string switch v := dbValue.(type) { case string: str = v case []byte: str = string(v) default: return fmt.Errorf("failed to unmarshal CSV value: %#v", dbValue) } // 二:核心:将数据表中的字段使用逗号分割,形成 []string fieldValue = strings.Split(str, ",") } // 三,将处理好的数据,设置到dst上 field.ReflectValueOf(ctx, dst).Set(reflect.ValueOf(fieldValue)) return nil } // 实现Value, serialize时执行 // fieldValue 模型的的字段值 func (CSVSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) { // 将字段值转换为可存储的CSV结构 return strings.Join(fieldValue.([]string), ","), nil } type Paper struct { gorm.Model Subject string //Tags []string // 使用 json 序列化器进行处理 Tags []string `gorm:"serializer:json"` // 使用自定义的编码器 Categories []string `gorm:"serializer:csv"` } // 2.注册到GORM中 // 3.测试 func CustomSerializer() { // 注册序列化器 schema.RegisterSerializer("csv", CSVSerializer{}) // 测试 if err := DB.AutoMigrate(&Paper{}); err != nil { log.Fatal(err) } // 常规操作 paper := &Paper{} paper.Subject = "使用自定义的Serializer操作Categories字段" paper.Tags = []string{"Go", "Serializer", "Gorm", "MySQL"} paper.Categories = []string{"Go", "Serializer", "Gorm", "MySQL"} // create 会执行序列化工作,serialize if err := DB.Create(paper).Error; err != nil { log.Fatal(err) } // 查询 newPaper := &Paper{} // First会执行反序列化工作,unserialize DB.First(newPaper, paper.ID) fmt.Printf("%+v\n", newPaper) } // 用于处理Blog新增的请求模型 type BlogPost struct { BlogBasic } // 用于更新 type BlogPut struct { ID uint BlogBasic } // 用于DB表交互的模型 type Blog struct { gorm.Model BlogBasic Author `gorm:"embeddedPrefix:author_"` } type BlogBasic struct { Subject string Summary string Content string }