第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

如何達(dá)到接口類型的結(jié)構(gòu)成員

如何達(dá)到接口類型的結(jié)構(gòu)成員

Go
素胚勾勒不出你 2023-02-14 18:11:38
我必須在切片中保留多類型結(jié)構(gòu)并為它們播種。我接受了接口類型的可變參數(shù)并 foreach 它們。如果我調(diào)用接口的方法,它就可以工作,但是當(dāng)我試圖訪問結(jié)構(gòu)時(shí),我不能。我該如何解決?注意:Seed() 方法返回?cái)?shù)據(jù)的文件名。界面:type Seeder interface {    Seed() string}方法:func (AirportCodes) Seed() string {    return "airport_codes.json"}播種機(jī)切片:seederModelList = []globals.Seeder{        m.AirportCodes{},        m.Term{},    }最后一個(gè),SeedSchema 函數(shù):func (db *Database) SeedSchema(models ...globals.Seeder) error {    var (        subjects []globals.Seeder        fileByte []byte        err      error        // tempMember map[string]interface{}    )    if len(models) == 0 {        subjects = seederModelList    } else {        subjects = models    }    for _, model := range subjects {        fileName := model.Seed()        fmt.Printf("%+v\n", model)        if fileByte, err = os.ReadFile("db/seeds/" + fileName); err != nil {            fmt.Println("asd", err)            // return err        }        if err = json.Unmarshal(fileByte, &model); err != nil {            fmt.Println("dsa", err)            // return err        }        modelType := reflect.TypeOf(model).Elem()        modelPtr2 := reflect.New(modelType)        fmt.Printf("%s\n", modelPtr2)     }    return nil}我可以達(dá)到精確的模型,但無法創(chuàng)建成員和種子。
查看完整描述

1 回答

?
白衣染霜花

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超10個(gè)贊

在評(píng)論中反復(fù)討論之后,我將在此處發(fā)布這個(gè)最小的答案。這絕不是一個(gè)明確的“這就是你所做的”類型的答案,但我希望這至少可以為你提供足夠的信息來幫助你開始。為了達(dá)到這一點(diǎn),我根據(jù)您提供的代碼片段做出了一些假設(shè),并且我假設(shè)您希望通過某種命令(例如)為數(shù)據(jù)庫播種your_bin seed。這意味著做出了以下假設(shè):

  1. 存在模式和相應(yīng)的模型/類型(類似AirportCodes等)

  2. 每種類型都有自己的源文件(名稱來自Seed()方法,返回一個(gè).json文件名)

  3. 因此,假定種子數(shù)據(jù)的格式類似于[{"seed": "data"}, {"more": "data"}].

  4. 可以附加種子文件,如果模式發(fā)生變化,種子文件中的數(shù)據(jù)也可以一起更改。這在 ATM 中不太重要,但仍然是一個(gè)應(yīng)該注意的假設(shè)。

好的,讓我們首先將所有 JSON 文件移動(dòng)到可預(yù)測(cè)的位置。在一個(gè)相當(dāng)大的真實(shí)世界應(yīng)用程序中,您會(huì)使用類似XDG 基本路徑的東西,但為了簡(jiǎn)潔起見,我們假設(shè)您在一個(gè)臨時(shí)容器中運(yùn)行它,并且/所有相關(guān)資產(chǎn)都已復(fù)制到所述容器中。

將所有種子文件放在seed_data目錄下的基本路徑中是有意義的。每個(gè)文件都包含特定表的種子數(shù)據(jù),因此一個(gè)文件中的所有數(shù)據(jù)都整齊地映射到一個(gè)模型上。讓我們暫時(shí)忽略關(guān)系數(shù)據(jù)。我們只是假設(shè),現(xiàn)在,這些文件中的數(shù)據(jù)至少在內(nèi)部是一致的,并且任何X-to-X關(guān)系數(shù)據(jù)都必須具有正確的 ID 字段,允許 JOIN 等。


開始吧

所以我們有了我們的模型,以及 JSON 文件中的數(shù)據(jù)。現(xiàn)在我們可以只創(chuàng)建所述模型的一部分,確保在插入其他數(shù)據(jù)之前您想要/需要存在的數(shù)據(jù)表示為比另一個(gè)更高的條目(較低的索引)。有點(diǎn)像這樣:

seederModelList = []globals.Seeder{

    m.AirportCodes{}, // seeds before Term

    m.Term{},         // seeds after AirportCodes

}

但是,或者從這個(gè)方法返回文件名Seed,為什么不傳入連接并讓模型像這樣處理自己的數(shù)據(jù):


func (_ AirportCodes) Seed(db *gorm.DB) error {

    // we know what file this model uses

    data, err := os.ReadFile("seed_data/airport_codes.json")

    if err != nil {

        return err

    }

    // we have the data, we can unmarshal it as AirportCode instances

    codes := []*AirportCodes{}

    if err := json.Unmarshal(data, &codes); err != nil {

        return err

    }

    // now INSERT, UPDATE, or UPSERT:

    db.Clauses(clause.OnConflict{

        UpdateAll: true,

    }).Create(&codes)

}

對(duì)其他模型執(zhí)行相同的操作,例如Terms:


func (_ Terms) Seed(db *gorm.DB) error {

    // we know what file this model uses

    data, err := os.ReadFile("seed_data/terms.json")

    if err != nil {

        return err

    }

    // we have the data, we can unmarshal it as Terms instances

    terms := []*Terms{}

    if err := json.Unmarshal(data, &terms); err != nil {

        return err

    }

    // now INSERT, UPDATE, or UPSERT:

    return db.Clauses(clause.OnConflict{

        UpdateAll: true,

    }).Create(&terms)

}

當(dāng)然,考慮到我們?cè)谀P椭杏袛?shù)據(jù)庫訪問權(quán)限,這確實(shí)會(huì)導(dǎo)致一些混亂,如果你問我的話,它實(shí)際上應(yīng)該只是一個(gè) DTO。這在錯(cuò)誤處理方面也有很多不足之處,但它的基本要點(diǎn)是:


func main() {

    db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) // omitted error handling for brevity

    seeds := []interface{

        Seed(*gorm.DB) error

    }{

        model.AirportCodes{},

        model.Terms{},

        // etc...

    }

    for _, m := range seeds {

        if err := m.Seed(db); err != nil {

            panic(err)

        }

    }

    db.Close()

}

好的,這應(yīng)該讓我們開始了,但讓我們通過以下方式將這一切變成更好的東西:

  1. 將整個(gè)數(shù)據(jù)庫交互移出 DTO/模型

  2. 將事情包裝到事務(wù)中,這樣我們就可以回滾錯(cuò)誤

  3. 稍微更新初始切片以使事情更清晰

因此,如前所述,我假設(shè)您有存儲(chǔ)庫之類的東西來處理單獨(dú)包中的數(shù)據(jù)庫交互。我們不應(yīng)該調(diào)用Seed模型并將數(shù)據(jù)庫連接傳遞給模型,而應(yīng)該依賴我們的存儲(chǔ)庫:

db, _ := gorm.Open() // same as before

acs := repo.NewAirportCodes(db) // pass in connection

tms := repo.NewTerms(db) // again...

現(xiàn)在我們的模型仍然可以返回 JSON 文件名,或者我們可以將其作為constrepos 中的一個(gè)。在這一點(diǎn)上,這并不重要。最主要的是,我們可以在存儲(chǔ)庫中完成實(shí)際的數(shù)據(jù)插入。


如果你愿意,你可以將你的種子切片更改為這樣的東西:


calls := []func() error{

    acs.Seed, // assuming your repo has a Seed function that does what it's supposed to do

    tms.Seed,

}

然后循環(huán)執(zhí)行所有播種:


for _, c := range calls {

    if err := c(); err != nil {

        panic(err)

    }

}

現(xiàn)在,這只剩下交易問題了。值得慶幸的是,gorm 使這變得非常簡(jiǎn)單:


db, _ := gorm.Open()

db.Transaction(func(tx *gorm.DB) error {

    acs := repo.NewAirportCodes(tx) // create repo's, but use TX for connection

    if err := acs.Seed(); err != nil {

        return err // returning an error will automatically rollback the transaction

    }

    tms := repo.NewTerms(tx)

    if err := tms.Seed(); err != nil {

        return err

    }

    return nil // commit transaction

})

您可以在這里擺弄更多的東西,例如創(chuàng)建可以單獨(dú)提交的相關(guān)數(shù)據(jù)批次,您可以添加更精確的錯(cuò)誤處理和更多信息的日志記錄,更好地處理沖突(區(qū)分 CREATE 和 UPDATE 等...)。不過,最重要的是,有一點(diǎn)值得牢記:


Gorm有一個(gè)遷移系統(tǒng)

我不得不承認(rèn),我已經(jīng)有一段時(shí)間沒有處理 gorm 了,但是 IIRC,如果模型發(fā)生變化,你可以讓表自動(dòng)遷移,并在啟動(dòng)時(shí)運(yùn)行自定義 go 代碼和/或 SQL 文件,這些都可以使用,相當(dāng)容易地播種數(shù)據(jù)??赡苤档醚芯恳幌滤目尚行浴?/p>


查看完整回答
反對(duì) 回復(fù) 2023-02-14
  • 1 回答
  • 0 關(guān)注
  • 97 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)