Go Webå¼åæ©å±é¡¹-å ¶ä»é å¥æ¡æ¶
ä½è ï¼å¯ä¹å¯ä¹å¯ï¼https://blog.csdn.net/weixin_44494373
ä¸ä¸ç¯ï¼Go Webå¼åå ¥é¨æåï¼ååï¼
å 容ï¼Go Webå¼åå¥è£ ï¼Ginï¼Gormï¼viperï¼validatorï¼zapï¼go-redisï¼grpc
æ¬æé¾åº¦ï¼éåå ¥é¨
ä¸åé¨åï¼æ们讲äºè®²Ginï¼æ³åå°webå¼åï¼æ们ç°å¨å·²ç»æäºåºç¡çMVCï¼æ们åªéè¦ORMæ¡æ¶ï¼æä½æ°æ®åºï¼æ¥å¿æ¡æ¶å°±è½æ»¡è¶³åºæ¬80%çéæ±äºï¼å次ä¹å¤ï¼å°±æ¯é ç½®æ件çæ¯æï¼rpcå¾®æå¡ä½ç³»æ¯æ
æ们ä¸ç¹ä¸ç¹æ¥æ©å±æ们çç¥è¯èå´ï¼ç¸æ¯åä½å·²ç»å¾å¿æ¥äºï¼é£æ们æç §è¿æ ·çæµç¨è¿è¡è®²è§£
ORMæ¡æ¶gorm -> æ¥å¿æ¡æ¶ï¼logrusãzap -> é ç½®æ件viper
ç¨Gormæ¥å¼å¯ä½ çCRUDä¹æ ï¼ä¸æ¯
å夫åæ·±ï¼ä¹éä¸äºCRUDçå½è¿ï¼æä¸å¤§ä½¬çä¸åï¼ä¸å¨ä¸æ§èºä¸çå·¥ä½ï¼å¨äºå¨ä»ä¹å°ç¹æ§èºä¸ï¼ï¼å¼ç©ç¬ï¼
Goæ¯ç¼ç¨è¯è¨éé¢çæ°çå¿è¿ç§äºæ å°±ä¸ç¨å强è°äºï¼æ°æ¶ä»£çCRUDï¼å¸å¸å¸ï¼ORMæä½ï¼å ä¸Goç®æ´ç追æ±ï¼GoçORMæ¡æ¶ç¨èµ·æ¥å¾è½»æ¾ï¼ä½æ¯ç»éªåè¯æï¼ç¨èµ·æ¥è¶ç®åï¼å¬èµ·æ¥è¶å ¨èªå¨çä¸è¥¿ï¼é½è¶ææï¼å£°æï¼æ¬å¥ä¸Kubernetes没æä»»ä½å ³ç³»ï¼
è¿éä¹ç®æ个éå§ï¼å·¥å ·èªå¨åæ¯å¥½äºï¼ä½æ¯è¿æå³çä½ å¯è½ä¼æéè¦è¿å ¥è¿èªå¨åç代ç ä¸ï¼ççä»çåçï¼æ¾å°ä½ ç解ç
æ¥ï¼å ç ä¸ä¸gormçå®æ¹ææ¡£ï¼ææ¡£å°å
å®æ¹ææ¡£åçå¾æ£ï¼å¤ççå®æ¹ææ¡£ï¼æ¯ç«ä¸æçæ¬ï¼
åå°è¿éï¼å¼å¼åå»å¤ä¹ äºä¸éææ¡£ï¼gormçææ¡£ï¼ç¡®å®ãã太å°ä½äºï¼å»ºè®®åä½ççå®æ¹ææ¡£å§ï¼è¿éæç»å¤§å®¶è®²ä¸ä¸åºæ¬çæ路让大家对gorméçä¸äºæ¦å¿µæ个åºç¡ç认è¯
ä½æ¯ä¸åGormï¼æ»æè§å¾ç©ºèï¼ææ¥æ³å»ï¼æåè¿æ¯åäºåºæ¥ï¼æä¼å°½éç¨ç®å便äºç解çæ¹å¼å¸®å©å¤§å®¶äºè§£gormï¼åé¢å°±åªéè¦å¨å®æ¹ææ¡£æ¾apiäº
æä½æ°æ®åºï¼ä¸è¬éè¦ä¸¤ä¸ªé¨åï¼1ãæ°æ®åºé©±å¨ 2ãormæ¡æ¶
èä¸ä¸ªormæ¡æ¶ï¼å¤§è´ä¼æè¿äºæ建
- ç±»ä¸è¡¨çæ å°
- 建ç«æ°æ®åºè¿æ¥
- æ°æ®åºè¿æ¥æ±
- CRUDæä½
- äºå¡æ§å¶
- æ¥å¿é ç½®
è¿å 个æ¥éª¤ä¹æ¯æ们使ç¨ä¸ä¸ªORMæ¡æ¶çåºæ¬æ¥éª¤
æ°æ®åºè¡¨æ å°
gorm没æå¦è¾è¹å¾ï¼æ¯å¾ç»å ¸çç±»å->表ï¼å段对åºè¡¨å段
æ们å建ä¸ä¸ªmodel
package model
// dataå°ä¼åæ表å称
type Data struct {
ID uint `json:"id,omitempty" gorm:"primaryKey"`
Msg string `json:"msg,omitempty" gorm:"type:varchar(10) unique"`
}
å ³äºè¡¨åä¸å段è¿ééè¦æ³¨æ以ä¸
GORMå¨å段å表é¢ç约å®
ä½¿ç¨ ID
ä½ä¸ºä¸»é®
ID
é»è®¤æ åµä¸ï¼GORM ä¼ä½¿ç¨
ID
ä½ä¸ºè¡¨ç主é®ã
type User struct {
ID string // é»è®¤æ
åµä¸ï¼å为 `ID` çå段ä¼ä½ä¸ºè¡¨ç主é®
Name string
}
ä½ å¯ä»¥éè¿æ ç¾
primaryKey
å°å ¶å®å段设为主é®
// å° `UUID` 设为主é®
type Animal struct {
ID int64
UUID string `gorm:"primaryKey"`
Name string
Age int64
}
æ¤å¤ï¼æ¨è¿å¯ä»¥çç å¤å主é®
å¤æ°è¡¨å
GORM 使ç¨ç»æä½åç
èå½¢å½å
ä½ä¸ºè¡¨åã对äºç»æä½
User
ï¼æ ¹æ®çº¦å®ï¼å ¶è¡¨å为
users
è¿éæå¾çæï¼æ们使ç¨AaBcä¼è¢«å建为aa_bcsï¼ä½æ¯æ们å½å为Dataï¼å°å建为data
æ»ä¹ï¼å®æ¹å¹¶æ²¡æä»ç»çåè¿°è¿éçé»è¾ï¼å¾æ å¥ï¼æ们åªè½è¢«é¼å次æå¼æºç ï¼å¥½è¶ï¼
è¿å ¥(db *DB) AutoMigrate(dst â¦interface{})æ¹æ³ï¼
æ们åç°ä»æ¯
éé
å¨æ¨¡å¼
ï¼è°ç¨äºdb.Migrator().AutoMigrate(dstâ¦)
è¿å ¥db.Migrator().AutoMigrate(dstâ¦)ï¼è¿ä¸ªæ¥å£åªæä¸ä¸ªå®ç°ç±»ï¼å¦¥å¦¥çéé å¨æ¨¡å¼
å¨è¿éï¼æ们大è´çäºçï¼é»è¾å为å建åä¿®æ¹è¡¨ï¼ä¸ç¨å¤æ³ï¼ä»ä»¬ççç¥ä¸å®æ¯ä¸æ ·çï¼æ们çcreateå³å¯
代ç è´´å¨äºä¸é¢ï¼å¤§å®¶æ¥ä¸èµ·è§èµä¸ä¸ï¼gormçéªæä½ï¼åæ¥ä¹å°±æ¯sqlçæ¼æ¥ç½¢äº
åä½å å¤ä¹ ä¸ä¸sqlå建表çè¯å¥
CREATE TABLE Persons
(
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);
大æ¦ççå°±è¡ï¼æµç¨å ¶å®å¾ç®åï¼å°±æ¯æ¼ååºä¸ä¸ªsql
func (m Migrator) CreateTable(values ...interface{}) error {
// ä¼ è¿æ¥çæ¯å¤ä¸ªè¡¨ï¼éåå建æ¯ä¸ä¸ª
for _, value := range m.ReorderModels(values, false) {
// å¼ä¸ä¸ªsession
tx := m.DB.Session(&gorm.Session{})
// å¼å§æ¼æ¥sql
if err := m.RunWithValue(value, func(stmt *gorm.Statement) (errr error) {
// CREATE TABLE ? (
var (
// sqlè¯å¥ï¼åæ°ç¨?
createTableSQL = "CREATE TABLE ? ("
// sqlåæ°
values = []interface{}{m.CurrentTable(stmt)}
hasPrimaryKeyInDataType bool
)
// æ¼æ¥ä¸æ¯ä¸ä¸ªå段ï¼è¿ä¼å ä¸PRIMARY KEY
// CREATE TABLE ? ( ? ? )
for _, dbName := range stmt.Schema.DBNames {
field := stmt.Schema.FieldsByDBName[dbName]
createTableSQL += "? ?"
// è·åæ ç¾ï¼ååºå符串 PRIMARY KEY
hasPrimaryKeyInDataType = hasPrimaryKeyInDataType || strings.Contains(strings.ToUpper(string(field.DataType)), "PRIMARY KEY")
values = append(values, clause.Column{Name: dbName}, m.DB.Migrator().FullDataTypeOf(field))
createTableSQL += ","
}
if !hasPrimaryKeyInDataType && len(stmt.Schema.PrimaryFields) > 0 {
createTableSQL += "PRIMARY KEY ?,"
primaryKeys := []interface{}{}
for _, field := range stmt.Schema.PrimaryFields {
primaryKeys = append(primaryKeys, clause.Column{Name: field.DBName})
}
values = append(values, primaryKeys)
}
// ç´¢å¼é»è¾
for _, idx := range stmt.Schema.ParseIndexes() {
if m.CreateIndexAfterCreateTable {
defer func(value interface{}, name string) {
if errr == nil {
errr = tx.Migrator().CreateIndex(value, name)
}
}(value, idx.Name)
} else {
if idx.Class != "" {
createTableSQL += idx.Class + " "
}
createTableSQL += "INDEX ? ?"
if idx.Option != "" {
createTableSQL += " " + idx.Option
}
createTableSQL += ","
values = append(values, clause.Expr{SQL: idx.Name}, tx.Migrator().(BuildIndexOptionsInterface).BuildIndexOptions(idx.Fields, stmt))
}
}
// å
³ç³»
for _, rel := range stmt.Schema.Relationships.Relations {
if !m.DB.DisableForeignKeyConstraintWhenMigrating {
if constraint := rel.ParseConstraint(); constraint != nil {
if constraint.Schema == stmt.Schema {
sql, vars := buildConstraint(constraint)
createTableSQL += sql + ","
values = append(values, vars...)
}
}
}
}
for _, chk := range stmt.Schema.ParseCheckConstraints() {
createTableSQL += "CONSTRAINT ? CHECK (?),"
values = append(values, clause.Column{Name: chk.Name}, clause.Expr{SQL: chk.Constraint})
}
// è¦æ¯ç»å°¾æ, å°±å»æ
createTableSQL = strings.TrimSuffix(createTableSQL, ",")
createTableSQL += ")"
if tableOption, ok := m.DB.Get("gorm:table_options"); ok {
createTableSQL += fmt.Sprint(tableOption)
}
// è·sql
errr = tx.Exec(createTableSQL, values...).Error
return errr
}); err != nil {
return err
}
}
return nil
}
诶ï¼ä¸å¯¹åï¼è¿é好åï¼æ²¡æå¤çå段åï¼ð ï¼ä¸å¥½ææï¼æ æçï¼è¿ä¸æ¿è®¤
æ们åå°ä¸ä¸çº§ï¼åç°è¿éæ个ReorderModelsçæ¹æ³ï¼å¥½å®¶ä¼å°±æ¯ä½ äºï¼æå¼çç
è¿ä¸ªæ¹æ³éé¢ï¼æè¿æ ·ä¸æ®µä»£ç ï¼
parseï¼parse valueï¼è¿æ¯ç¼ç¨çå¤ç解ææ°æ®çå®è¯ï¼æ们éå®è¿ä¸ªæ¹æ³ï¼ç¹è¿å»
schemaæ¯å ³ç³»çææï¼ç´æ¥ç¹è¿å»ï¼æ们çå°äºåå°ï¼æ²¡æ¯ç äºï¼å°±æ¯è¿éäº
é¦å å°±æ¯ç»å ¸çåå°å¤çï¼éªè¯ç±»åï¼éé ç±»å
æ£æ¥ç±»åæ¯å¦å®ç°äºæ¥å£TableNameï¼å¦æ使ç¨äºï¼å°±ç´æ¥è°ç¨è¿å
ç¶åå©ç¨å¾å°çç±»åå建ä¸ä¸ªæ°ç空对象
æ¥çç¨namer.TableName()è·å解æåç表åï¼å¥½å®¶ä¼ï¼å¯æ¾å°ä½ äº
// TableName convert string to table name
func (ns NamingStrategy) TableName(str string) string {
// åæ°çtableï¼è¯´æè¿éæ¥å¤ææ«å°¾æ¯ä¸æ¯å s
if ns.SingularTable {
return ns.TablePrefix + ns.toDBName(str)
}
// å ä¸s
return ns.TablePrefix + inflection.Plural(ns.toDBName(str))
}
// å°å符串å¤ç
// 大å°ååå¨ï¼é©¼å³°è½¬ä¸å线形å¼ï¼æ³çå¯ä»¥çï¼å
¶å®å°±æ¯ä¸ä¸ªå符ä¸ä¸ªå符å¤æï¼å¤æå½åæ¯è½¬åï¼æå
¥ï¼è¿æ¯å ä¸å线
// Dat->dat
// Data->data
func (ns NamingStrategy) toDBName(name string) string {
if name == "" {
return ""
}
if ns.NameReplacer != nil {
name = ns.NameReplacer.Replace(name)
}
if ns.NoLowerCase {
return name
}
var (
value = commonInitialismsReplacer.Replace(name)
buf strings.Builder
lastCase, nextCase, nextNumber bool // upper case == true
curCase = value[0] <= 'Z' && value[0] >= 'A'
)
// éå表å
for i, v := range value[:len(value)-1] {
nextCase = value[i+1] <= 'Z' && value[i+1] >= 'A'
nextNumber = value[i+1] >= '0' && value[i+1] <= '9'
if curCase {
if lastCase && (nextCase || nextNumber) {
buf.WriteRune(v + 32)
} else {
if i > 0 && value[i-1] != '_' && value[i+1] != '_' {
buf.WriteByte('_')
}
buf.WriteRune(v + 32)
}
} else {
buf.WriteRune(v)
}
lastCase = curCase
curCase = nextCase
}
if curCase {
if !lastCase && len(value) > 1 {
buf.WriteByte('_')
}
buf.WriteByte(value[len(value)-1] + 32)
} else {
buf.WriteByte(value[len(value)-1])
}
ret := buf.String()
return ret
}
ç¶å Plural(str string) string å¤çå·²ç»å¤§å°åå¤çè¿çå符串
Plural å¤æ°
// Plural converts a word to its plural form
func Plural(str string) string {
for _, inflection := range compiledPluralMaps {
if inflection.regexp.MatchString(str) {
return inflection.regexp.ReplaceAllString(str, inflection.replace)
}
}
return str
}
ççï¼è¿ä¸ªä»£ç ï¼é©¬è¨å¡ï¼ä¸ä¼ï¼ï¼ä»ç«ç¶æ¯æ举ææçç¹æ®å¤æ°ï¼æ¯å¦fishé±¼ï¼çå¤æ°ä¸ºfishï¼acçå¤æ°ä¸ºacsï¼ãããå¯çæä½ ç
é®é¢è§£å³äºå å¼ä»¬ï¼data表åï¼æ¯å 为ããdataæ¯ä¸å¯æ°ï¼è±è¯ç¥è¯ï¼
æ»ç»ï¼Gormå建表ï¼é»è®¤ä¼ä½¿ç¨å¤æ°å表åï¼åæ¶è¯ä¹ç¬¦åè±æè¯æ³ï¼å°½ç®¡å½¢å¼å¾ççï¼ï¼å¯ä»¥éè¿Configè¿è¡éæ©æ¯å¦ä½¿ç¨å¤æ°ã
TableName
æ¨å¯ä»¥å®ç°
Tabler
æ¥å£æ¥æ´æ¹é»è®¤è¡¨åï¼ä¾å¦ï¼
type Tabler interface {
TableName() string
}
// TableName ä¼å° User ç表åéå为 `profiles`
func (User) TableName() string {
return "profiles"
}
注æï¼ä¸æ¯æå¨æååï¼å®ä¼è¢«ç¼åä¸æ¥ä»¥ä¾¿åç»ä½¿ç¨ãæ³è¦ä½¿ç¨å¨æ表åï¼ä½ å¯ä»¥ä½¿ç¨
TableName
ï¼ä¾å¦ï¼
Scopes
func UserTable(user User) func (tx *gorm.DB) *gorm.DB {
return func (tx *gorm.DB) *gorm.DB {
if user.Admin {
return tx.Table("admin_users")
}
return tx.Table("users")
}
}
db.Scopes(UserTable(user)).Create(&user)
临æ¶æå®è¡¨å
æ¨å¯ä»¥ä½¿ç¨
Table
æ¹æ³ä¸´æ¶æå®è¡¨åï¼ä¾å¦ï¼
// æ ¹æ® User çå段å建 `deleted_users` 表
db.Table("deleted_users").AutoMigrate(&User{})
// ä»å¦ä¸å¼ 表æ¥è¯¢æ°æ®
var deletedUsers []User
db.Table("deleted_users").Find(&deletedUsers)
// SELECT * FROM deleted_users;
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
// DELETE FROM deleted_users WHERE name = 'jinzhu';
æ¥ç from åæ¥è¯¢ äºè§£å¦ä½å¨ FROM åå¥ä¸ä½¿ç¨åæ¥è¯¢
å½åçç¥
GORM å 许ç¨æ·éè¿è¦çé»è®¤ç
å½åçç¥
æ´æ¹é»è®¤çå½å约å®ï¼å½åçç¥è¢«ç¨äºæ建ï¼
TableName
ã
ColumnName
ã
JoinTableName
ã
RelationshipFKName
ã
CheckerName
ã
IndexName
ãæ¥ç GORM é ç½® è·å详æ
åå
æ ¹æ®çº¦å®ï¼æ°æ®è¡¨çåå使ç¨çæ¯ struct å段åç
èå½¢å½å
type User struct {
ID uint // ååæ¯ `id`
Name string // ååæ¯ `name`
Birthday time.Time // ååæ¯ `birthday`
CreatedAt time.Time // ååæ¯ `created_at`
}
æ¨å¯ä»¥ä½¿ç¨
column
æ ç¾æ
å½åçç¥
æ¥è¦çåå
type Animal struct {
AnimalID int64 `gorm:"column:beast_id"` // å°åå设为 `beast_id`
Birthday time.Time `gorm:"column:day_of_the_beast"` // å°åå设为 `day_of_the_beast`
Age int64 `gorm:"column:age_of_the_beast"` // å°åå设为 `age_of_the_beast`
}
æ¶é´æ³è¿½è¸ª
CreatedAt
对äºæ
CreatedAt
å段ç模åï¼å建记å½æ¶ï¼å¦æ该å段å¼ä¸ºé¶å¼ï¼åå°è¯¥å段çå¼è®¾ä¸ºå½åæ¶é´
db.Create(&user) // å° `CreatedAt` 设为å½åæ¶é´
user2 := User{Name: "jinzhu", CreatedAt: time.Now()}
db.Create(&user2) // user2 ç `CreatedAt` ä¸ä¼è¢«ä¿®æ¹
// æ³è¦ä¿®æ¹è¯¥å¼ï¼æ¨å¯ä»¥ä½¿ç¨ `Update`
db.Model(&user).Update("CreatedAt", time.Now())
UpdatedAt
对äºæ
UpdatedAt
å段ç模åï¼æ´æ°è®°å½æ¶ï¼å°è¯¥å段çå¼è®¾ä¸ºå½åæ¶é´ãå建记å½æ¶ï¼å¦æ该å段å¼ä¸ºé¶å¼ï¼åå°è¯¥å段çå¼è®¾ä¸ºå½åæ¶é´
db.Save(&user) // å° `UpdatedAt` 设为å½åæ¶é´
db.Model(&user).Update("name", "jinzhu") // ä¼å° `UpdatedAt` 设为å½åæ¶é´
db.Model(&user).UpdateColumn("name", "jinzhu") // `UpdatedAt` ä¸ä¼è¢«ä¿®æ¹
user2 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Create(&user2) // å建记å½æ¶ï¼user2 ç `UpdatedAt` ä¸ä¼è¢«ä¿®æ¹
user3 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Save(&user3) // æ´æ°ä¸ï¼user3 ç `UpdatedAt` ä¼ä¿®æ¹ä¸ºå½åæ¶é´
注æ GORM æ¯ææ¥æå¤ç§ç±»åçæ¶é´è¿½è¸ªå段ãå¯ä»¥æ ¹æ® UNIXï¼æ¯«/纳ï¼ç§ï¼æ¥ç Model è·å详æ
使ç¨gorm:"primaryKey"æ ç¾å¯ä»¥æå®ä¸»é®
gormæ¯æå建æ°æ®è¡¨ï¼ä½¿ç¨AutoMigrateå³å¯
err = db.AutoMigrate(&model.Data{})
if err != nil {
fmt.Printf("error :%s",err.Error())
}
æ们æ§è¡è¿ä¸ªå½ä»¤åï¼åç°å符串类å为longTextè¿ä¸ä¸ä¸å¯åï¼æ²¡å ³ç³»ï¼goæä¾äºä¸°å¯çå段æ ç¾æ¯æï¼å¸®å©æ们å®ä¹ä¸ä¸ªæ°æ®è¡¨
声æ model æ¶ï¼tag æ¯å¯éçï¼GORM æ¯æä»¥ä¸ tagï¼ tag å大å°åä¸ææï¼ä½å»ºè®®ä½¿ç¨
camelCase
é£æ ¼
æ ç¾å | 说æ |
---|---|
column | æå® db åå |
type | åæ°æ®ç±»åï¼æ¨è使ç¨å
¼å®¹æ§å¥½çéç¨ç±»åï¼ä¾å¦ï¼æææ°æ®åºé½æ¯æ boolãintãuintãfloatãstringãtimeãbytes 并ä¸å¯ä»¥åå
¶ä»æ ç¾ä¸èµ·ä½¿ç¨ï¼ä¾å¦ï¼ ã , ⦠å è¿æ ·æå®æ°æ®åºæ°æ®ç±»åä¹æ¯æ¯æçãå¨ä½¿ç¨æå®æ°æ®åºæ°æ®ç±»åæ¶ï¼å®éè¦æ¯å®æ´çæ°æ®åºæ°æ®ç±»åï¼å¦ï¼ |
size | æå®å大å°ï¼ä¾å¦ï¼ |
primaryKey | æå®åä¸ºä¸»é® |
unique | æå®å为å¯ä¸ |
default | æå®åçé»è®¤å¼ |
precision | æå®åç精度 |
scale | æå®åå¤§å° |
not null | æå®å为 NOT NULL |
autoIncrement | æå®å为èªå¨å¢é¿ |
autoIncrementIncrement | èªå¨æ¥é¿ï¼æ§å¶è¿ç»è®°å½ä¹é´çé´é |
embedded | åµå¥å段 |
embeddedPrefix | åµå ¥å段çåååç¼ |
autoCreateTime | å建æ¶è¿½è¸ªå½åæ¶é´ï¼å¯¹äº å段ï¼å®ä¼è¿½è¸ªç§çº§æ¶é´æ³ï¼æ¨å¯ä»¥ä½¿ç¨ / æ¥è¿½è¸ªçº³ç§ã毫ç§æ¶é´æ³ï¼ä¾å¦ï¼ |
autoUpdateTime | å建/æ´æ°æ¶è¿½è¸ªå½åæ¶é´ï¼å¯¹äº å段ï¼å®ä¼è¿½è¸ªç§çº§æ¶é´æ³ï¼æ¨å¯ä»¥ä½¿ç¨ / æ¥è¿½è¸ªçº³ç§ã毫ç§æ¶é´æ³ï¼ä¾å¦ï¼ |
index | æ ¹æ®åæ°å建索å¼ï¼å¤ä¸ªå段使ç¨ç¸åçå称åå建å¤åç´¢å¼ï¼æ¥ç ç´¢å¼ è·å详æ |
uniqueIndex | ä¸ ç¸åï¼ä½å建çæ¯å¯ä¸ç´¢å¼ |
check | å建æ£æ¥çº¦æï¼ä¾å¦ ï¼æ¥ç 约æ è·å详æ
|
<- | 设置å段åå
¥çæéï¼ åªå建ã åªæ´æ°ã æ åå
¥æéã å建åæ´æ°æé |
-> | 设置å段读çæéï¼ æ 读æé |
- | 忽ç¥è¯¥åæ®µï¼ æ 读åæé |
comment | è¿ç§»æ¶ä¸ºå段添å 注é |
为äºæ大åå¤ç¨å段ï¼æ们å¯è½ä¼ç¨åµå¥çæ¹å¼ï¼æ¥è¡¨è¾¾ä¸ä¸ªæ°æ®ï¼å¨Goéé¢ä¹æ¯æ¯æåµå¥ç
è¿éè¡¥å ä¸ç¹å®æ¹æ²¡ææå°çï¼tagæä¹ç¨233ï¼äºå®ä¸ï¼gormçtagæ¯è¿ä¹ç¨ç
package model
// dataå°ä¼åæ表å称
type Data struct {
ID uint `json:"id,omitempty" gorm:"primaryKey"`
// é½æ¯ç¨gormæ ç¾ï¼ç©ºæ ¼åºå
Msg string `json:"msg,omitempty" gorm:"type:varchar(10) unique"`
}
以ä¸æ¥èªå®æ¹ææ¡£
åµå ¥ç»æä½
对äºå¿åå段ï¼GORM ä¼å°å ¶å段å å«å¨ç¶ç»æä½ä¸ï¼ä¾å¦ï¼
type User struct {
gorm.Model
Name string
}
// çæäº
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Name string
}
对äºæ£å¸¸çç»æä½å段ï¼ä½ ä¹å¯ä»¥éè¿æ ç¾
embedded
å°å ¶åµå ¥ï¼ä¾å¦ï¼
type Author struct {
Name string
Email string
}
type Blog struct {
ID int
Author Author `gorm:"embedded"`
Upvotes int32
}
// çæäº
type Blog struct {
ID int64
Name string
Email string
Upvotes int32
}
并ä¸ï¼æ¨å¯ä»¥ä½¿ç¨æ ç¾
embeddedPrefix
æ¥ä¸º db ä¸çå段åæ·»å åç¼ï¼ä¾å¦ï¼
type Blog struct {
ID int
Author Author `gorm:"embedded;embeddedPrefix:author_"`
Upvotes int32
}
// çæäº
type Blog struct {
ID int64
AuthorName string
AuthorEmail string
Upvotes int32
}
å建è¿æ¥
å¦ä½å建ä¸ä¸ªæ°æ®åºè¿æ¥
æ们使ç¨å¤§ä¼ç¨çæå¤çæ°æ®åºMySQLï¼
é¦å éè¦æ们æ¾ä¸ä¸mysqlç驱å¨ï¼gormæä¾äºmysqlç驱å¨https://github.com/go-gorm/mysql
å¨ä½ ç项ç®è·¯å¾éé¢ï¼è·ä¿©å½ä»¤
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
使ç¨ä¸é¢çå½ä»¤å建ä¸ä¸ªæ°æ®åºè¿æ¥
// åè https://github.com/go-sql-driver/mysql#dsn-data-source-name è·å详æ
dsn := "user:[email protected](127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
ç°å¨æ们è·åå°çè¿ä¸ªdbåé*gorm.DBç±»åï¼gormä¸ginçé£æ ¼ç±»ä¼¼ï¼ä½¿ç¨ä¸ä¸ªç±»å®æææå¯è½çæä½
CRUD
GORMæ两ç§é£æ ¼æ¥è¿è¡sqlï¼ç¬¬ä¸ç§é£æ ¼ä¸ºé¾å¼è°ç¨ï¼ç¬¬äºç§é£æ ¼ä¸ºåçsql
å½ç¶ï¼é¾å¼è°ç¨æ´è½»æ¾ï¼ä¸è¬ç¨è¿ä¸ªå°±å¤äºï¼
å¨åå§åæµè¯æ°æ®ï¼æ¸ 空表çåºæ¯ï¼ç¨åçsqlæ´å¿«ï¼æ´ç´ç½
è¿éæåªç®å讲解éè¦çç¹ï¼æ´å¤å 容建议移æ¥å®æ¹ææ¡£ https://gorm.io/zh_CN/docs/create.html
çå®åºç¡åï¼åä½åæ¥ççä¸é¢çé®é¢
é¾å¼è°ç¨
GORMå é¨æå¾å¤apiï¼Whereï¼Orderï¼Fristï¼Lastï¼Findççï¼
è¿äºæ件å为ä¸å¤§ç±»ï¼é¾å¼æ¹æ³ï¼Finisheræ¹æ³ï¼æ°å»ºä¼è¯æ¹æ³
æ们å ä¸ç®¡åé¢ä¸¤ä¸ªï¼å æ¥ççè°ç¨é¾
è°ç¨é¾ï¼
æ们以Whereè¿è¡ä¸¾ä¾
// Where add conditions
func (db *DB) Where(query interface{}, args ...interface{}) (tx *DB) {
tx = db.getInstance()
if conds := tx.Statement.BuildCondition(query, args...); len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: conds})
}
return
}
ä»ä»£ç æ们å¯ä»¥çåºï¼é¦å è·ådbå é¨çtx对象ï¼ç¶åWhereè¯å¥ä¸ä¸æ¥æ¯æ¼æ¥åºæ¡ä»¶ï¼ç¶åè°ç¨dbå é¨txçAddClause()æ¹æ³ï¼å°æ¡ä»¶æ³¨åå°å é¨çtx对象ä¸ï¼ç¶åè¿åtx
é£ä¹è¿ä¸ªtxæ¯ä»ä¹ï¼getInstanceæ¯ä»ä¹ï¼
æ们æ¿åºget Instanceç代ç
func (db *DB) getInstance() *DB {
if db.clone > 0 {
tx := &DB{Config: db.Config, Error: db.Error}
if db.clone == 1 {
// clone with new statement
tx.Statement = &Statement{
DB: tx,
ConnPool: db.Statement.ConnPool,
Context: db.Statement.Context,
Clauses: map[string]clause.Clause{},
Vars: make([]interface{}, 0, 8),
}
} else {
// with clone statement
tx.Statement = db.Statement.clone()
tx.Statement.DB = tx
}
return tx
}
return db
}
ä»è¿æ®µä»£ç ï¼æ们å¯ä»¥çåºæ¥ï¼å¦æclone大äº0ï¼å°æ°å»ºä¸ä¸ªtxåºæ¥ï¼è¿ä¸ªtxå°±æ¯DBç±»åç对象ï¼ç¶åå¤ææ¯cloneè¿æ¯æ°å»ºï¼æ°å»ºçè¯å°±æ°å»ºä¸ä¸ªtx.Statementåºæ¥ï¼èä¸æ°å»ºçtxçclone为0
ä¹å°±æ¯è¯´ï¼æ们使ç¨openè·å¾çdbï¼æ¯ä¸ä¸ªæ ¹DBï¼å ¶cloneå¼ä¸º1ï¼å¨ä½¿ç¨å®æ¶ï¼å®å°å建æ°çDBï¼èå建åºçæ°DBï¼å ¶cloneå¼ä¸º0ï¼å°ç»§ç»ä½¿ç¨ä¸å»
è¿é大家è¦æ³¨æçæ¯ï¼gormåºå±å ¶å®è¿æ¯sqlçæ¼æ¥ï¼æ以åä½è¦æ³¨æsqlè¯æ³
å建ä¼è¯æ¨¡å¼
å¨ä¸é¢çåæä¸ï¼æ们åç°å½ä½¿ç¨dbå建ä¸ä¸ªæ°è°ç¨æ¶ï¼dbå é¨çclone为1ï¼ç¶åä¼å建æ°çDBæ¥ç»åé¢çè¯å¥æä½
é£ä¹è¿ä¸ªclone为1çè¯å¥æ¯ä»åªéæ¥çï¼
ââå建ä¼è¯æ¨¡å¼
æ°åå§åç
*gorm.DB
æè°ç¨
æ°å»ºä¼è¯æ¹æ³
æ们ç¹å¼
gorm.Open(mysql.Open(dsn), &gorm.Config{})
è¿ä¸ªä»£ç ï¼
å ¶ä¸æä¸è¡ä»£ç 为
okï¼å®é¤äºä¸ä¸ª
è¿æå°±æ¯æ°å»ºä¼è¯æ¹æ³ï¼æ²¡æ¯ç ï¼é½æ¯cloneå¼ä¸º1
// Session create new db session
func (db *DB) Session(config *Session) *DB {
var (
txConfig = *db.Config
tx = &DB{
Config: &txConfig,
Statement: db.Statement,
Error: db.Error,
clone: 1,
}
)
...
}
æ以å®ç½ç¤ºèä¸ï¼ä¸é¢çè¯å¥
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
// db æ¯ä¸ä¸ªåå®æåå§åç *gorm.DB å®ä¾ï¼å
¶å±äº `æ°å»ºä¼è¯æ¨¡å¼`
tx := db.Where("name = ?", "jinzhu")
// `Where("name = ?", "jinzhu")` æ¯ç¬¬ä¸ä¸ªè¢«è°ç¨çæ¹æ³ï¼å®å建äºä¸ä¸ªæ°ç `Statement` 并添å æ¡ä»¶
tx.Where("age = ?", 18).Find(&users)
// `tx.Where("age = ?", 18)` ä¼å¤ç¨ä¸é¢çé£ä¸ª `Statement`ï¼å¹¶åå
¶æ·»å æ¡ä»¶
// `Find(&users)` æ¯ä¸ä¸ª finisher æ¹æ³ï¼å®è¿è¡æ³¨åçæ¥è¯¢åè°ï¼çæ并è¿è¡ä¸é¢è¿æ¡ SQLï¼
// SELECT * FROM users WHERE name = 'jinzhu' AND age = 18
tx.Where("age = ?", 28).Find(&users)
// `tx.Where("age = ?", 18)` åæ ·ä¼å¤ç¨ä¸é¢çé£ä¸ª `Statement`ï¼å¹¶åå
¶æ·»å æ¡ä»¶
// `Find(&users)` æ¯ä¸ä¸ª finisher æ¹æ³ï¼å®è¿è¡æ³¨åçæ¥è¯¢åè°ï¼çæ并è¿è¡ä¸é¢è¿æ¡ SQLï¼
// SELECT * FROM users WHERE name = 'jinzhu' AND age = 18 AND age = 28;
注æï¼ å¨ç¤ºä¾ 2 ä¸ï¼ç¬¬ä¸ä¸ªæ¥è¯¢ä¼å½±å第äºä¸ªæ¥è¯¢çæç SQLï¼å 为 GORM å¤ç¨äº Statement
è¿å¯è½ä¼å¯¼è´é¢æä¹å¤çé®é¢ï¼æ¥ç åç¨å®å
¨ 以é¿å
该é®é¢
è¿æ®µè¯ï¼å°±å¾è½»æ¾å¯ä»¥ç解äºã
åç¨å®å ¨
å次ä¹å¤ï¼æç« è¿æå°äºåç¨å®å ¨ï¼ä¸ºä»ä¹è¿ä¹è¯´å¢ï¼åç¨å®å ¨ï¼ä¹å°±æ¯å ¶ä»è¯è¨éé¢çå¤çº¿ç¨å®å ¨ï¼ä¹å°±æ¯è¯´ï¼æ²¡æéï¼ä¸ºä»ä¹å¢ï¼
ââWhereçè¯å¥æä½çæ¯db对象å é¨çtx对象ï¼txå±äºä¸´çåºï¼æ以è¿æ¯å±é©çã
ç¶åå¨æ«å°¾è¡¥ä¸å¥ï¼
Order类似äºorder by è¯å¥ï¼Orderåæ¥Firstæè Lastæ¶ï¼Firstæè Lastçorder失æ
æè¿æ´»å¤èµ·æ¥äºï¼æ¬æ¬¡å°±å æ´å°è¿é
åç»ï¼æ¥å¿æ¡æ¶ï¼logrusãzap -> é ç½®æ件viper