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

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

Golang通用數(shù)據(jù)庫單條記錄轉(zhuǎn)json

Golang通用數(shù)據(jù)庫單條記錄轉(zhuǎn)json

Go
倚天杖 2023-05-15 15:32:50
我想從數(shù)據(jù)庫中檢索記錄并將其編組為 json。我有大約 30 個(gè)不同的表,所以我想要適用于所有這些表的通用函數(shù)。我使用 xorm 進(jìn)行數(shù)據(jù)庫訪問。我設(shè)法創(chuàng)建了檢索數(shù)據(jù)的 DRY 函數(shù),這主要?dú)w功于這個(gè)問答這有效,可以將所有記錄編組為 json:type user struct {   Id   int64  `json:"id"`   Name string `json:"name"`}// type post// etc.type tableRecord struct {    PrimaryKey string    Data       interface{}}var ListOfTables = map[string]tableRecord{    "users":{"id", &[]user{}},  // type user is struct for xorm with json annotation    //"posts":{"post_id", &[]post{}},    // etc.. }for tableName, rec := range ListOfTables {    err := xorm.Find(rec.Data)    if err != nil {        log.Print(err)    }    out, err := json.Marshal(rec.Data)    if err != nil {        log.Print(err)    }    log.Print(string(out)) // this yields json array}但是,我很難將單個(gè)記錄編組為 json。我四處尋找迭代 interface{} 的方法,它包含一個(gè)切片,找到了這個(gè)和類似的主題。試過:switch reflect.TypeOf(reflect.ValueOf(rec.Data).Elem().Interface()).Kind() {case reflect.Slice:    s := reflect.ValueOf(reflect.ValueOf(rec.Data).Elem().Interface())    for i := 0; i < s.Len(); i++ {        entry := s.Index(i)        log.Printf("%v\n", entry) // prints {1 John Doe}        // log.Print(reflect.ValueOf(entry))        data, err := json.MarshalIndent(entry, " ", "  ")        if err != nil {            log.Print(err)        }        log.Println(string(data)) // prints {} empty    }}  當(dāng)然,如果我指定它rec.Data是*[]user有效的,那么我將不得不為每個(gè)表重寫這樣的代碼,這不是我所追求的。switch t := rec.Data.(type) {case *[]user:    for _, entry := range *t {        // log.Printf("loop %v", entry)        data, err := json.MarshalIndent(entry, " ", "  ")        if err != nil {            log.Print(err)        }        log.Println(string(data)) // yields needed json for single record    }}或者也許有一種完全不同的、更好的方法來解決這個(gè)問題——數(shù)據(jù)庫的任何記錄到 json。
查看完整描述

1 回答

?
慕標(biāo)琳琳

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

因此,正如我在評(píng)論中提到的,如果您希望能夠從字段中獲取單個(gè)元素,最簡(jiǎn)單的方法tableRecord.Data就是將字段類型更改為實(shí)際類型:


type tableRecord struct {

    PrimaryKey string

    Data       []interface{} // slice of whatever

}

這樣,你可以寫一些非常通用的東西:


for tbl, record := range records {

    fmt.Printf("First record from table %s\n", tbl)

    b, _ := json.MarshalIndent(record[0], " ", "  ")

    fmt.Println(string(b))

    fmt.Prinln("other records...")

    b, _ = json.MarshalIndend(record[1:], " ", "  ")

    fmt.Println(string(b))

}

不過,如果我是你,我會(huì)考慮在我的數(shù)據(jù)庫類型中實(shí)現(xiàn)一個(gè)接口。類似的東西:


type DBType interface {

    PrimaryKey() string

    TableName() string // xorm can use this to get the table name

    Slice() []DBType // can return []user or whatever

}

所以你真的不需要tableRecord類型了,可以像這樣使用 var:


listOfTables := []DBType{user{}, ...}

for _, tbl := range listOfTables {

    data := tbl.Slice()

    // find data here

    fmt.Printf("First record from table %s\n", tbl.TableName())

    b, _ := json.MarshalIndent(data[0], " ", "  ")

    fmt.Println(string(b))

    fmt.Prinln("other records...")

    b, _ = json.MarshalIndend(data[1:], " ", "  ")

    fmt.Println(string(b))

}

所以 TL;DR 我的回答/評(píng)論中缺少的內(nèi)容:


[]user{}從 type (or []DBTable) to 的轉(zhuǎn)換[]interface{}不起作用,因?yàn)槟荒茉趩蝹€(gè)表達(dá)式中轉(zhuǎn)換切片中的所有元素。您必須創(chuàng)建第二個(gè)類型切片[]interface{}并像這樣復(fù)制值:


slice := userVar.Slice() data := make([]interface{}, len(slice)) for i := range slice { data[i] = slice[i] // 復(fù)制類型到 interface{} slice } 返回表記錄{userVar.PrimaryKey(), 數(shù)據(jù)}


我已經(jīng)創(chuàng)建了一個(gè)小的工作示例來說明如何使用上述接口。


演示

為避免太多混亂,您可以更改Slicefunc 以[]interface{}立即返回 a:


func(v T) Slice() []interface{

    return []interface{

        &T{},

    }

}

你的實(shí)施有什么問題Slice是你有這樣的事情:


func (u *user) Slice() []DBTable {

    u = &user{} // you're re-assigning the receiver, losing all state!

    return []DBTable{u}

}

接收器是指針類型,因此您所做的任何重新分配都會(huì)影響調(diào)用 func 的變量。那不是一個(gè)好主意。只使用值接收器,或者,如果你想確保接口只在指針變量上實(shí)現(xiàn)(一個(gè)常見的技巧,例如 gRPC 使用的)是像這樣實(shí)現(xiàn)函數(shù):


func(*user) Slice() []DBTable{

    return []DBTable{&user{}}

}

pb.go這個(gè)技巧的一個(gè)很好的例子可以在使用協(xié)議緩沖區(qū)時(shí)生成的文件中找到。消息類型將具有如下功能:


func(*MsgType) ProtoMessage() {}


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

添加回答

舉報(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)