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

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

如何使用接口來允許超過 1 種結(jié)構(gòu)類型以使代碼更有用?

如何使用接口來允許超過 1 種結(jié)構(gòu)類型以使代碼更有用?

Go
繁星點(diǎn)點(diǎn)滴滴 2022-01-10 14:32:37
我有一個(gè)看起來像這樣的結(jié)構(gòu):type BetaKey struct {    Id           int64  `json:"-"`    IssuerId     int64  `json:"-"          db:"issuer_id"`    SubjectEmail string `json:"-"          db:"subject_email"`    IssuedTime   int64  `json:"-"          db:"issued_time"`    ExpiryTime   int64  `json:"expiryTime" db:"expiry_time"`    Betakey      string `json:"accessKey"`    Description  string `json:"description"`}在同一個(gè)包中,我有一個(gè)返回切片的函數(shù)BetaKey:func buildResults(query string) ([]BetaKey, error) {    results := []BetaKey{}    rows, err := sql.DB.Queryx(query)    if err != nil {        return results, err    }    defer rows.Close()    for rows.Next() {        var bk BetaKey        err := rows.StructScan(&bk)        if err != nil {            return results, err        }        results = append(results, bk)    }    err = rows.Err()    if err != nil {        return results, err    }    return results, nil}我是否可以重寫此函數(shù),以便它接受查詢字符串和BetaKeyas類型interface{},并返回一個(gè)切片,interface{}以便我可以重用代碼而不是將其復(fù)制粘貼到每個(gè)包中,因?yàn)樗鼘?shí)際上是相同的但唯一的區(qū)別是改變的結(jié)構(gòu)的名稱。這可能嗎?這也是建議嗎?如果不是,那為什么?
查看完整描述

2 回答

?
搖曳的薔薇

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

泛型可以用來實(shí)現(xiàn)這樣的事情,但 Go 不支持泛型。要在 Go 中做你想做的事,你需要使用反射。


您可以更改您的函數(shù)以采用 1 個(gè)附加參數(shù),reflect.Type例如,它指定應(yīng)加載各個(gè)行的值的類型。


然后,您可以使用reflect.New()創(chuàng)建此類型的新值并獲取指向它的指針。您可以使用從值中Value.Interface()獲取作為類型的指針值。這個(gè)包裝指針現(xiàn)在可以傳遞給.interface{}reflect.Valueinterface{}Rows.StructScan()


如果您希望結(jié)果切片包含非指針值,您可以使用reflect.Indirect()來獲取指向的值(以及另一個(gè)reflect.Interface()將結(jié)構(gòu)值提取為interface{})。


示例代碼:


func buildResults(query string, t reflect.Type) ([]interface{}, error) {

    results := []interface{}{}

    rows, err := sql.DB.Queryx(query)

    if err != nil {

        return results, err

    }

    defer rows.Close()

    for rows.Next() {

        val := reflect.New(t)

        err := rows.StructScan(val.Interface())

        if err != nil {

            return results, err

        }

        i_ := reflect.Indirect(val)

        result = append(result, i_.Interface())

    }

    err = rows.Err()

    if err != nil {

        return results, err

    }

    return results, nil

}

它的核心是for塊:


val := reflect.New(t)                   // A pointer to a new value (of type t)

err := rows.StructScan(val.Interface()) // Pass the pointer to StructScan

if err != nil {

    return results, err

}

i_ := reflect.Indirect(val)             // Dereference the pointer

result = append(result, i_.Interface()) // And add the non-pointer to the result slice

以下是測(cè)試它的方法:


type BetaKey struct {

    Id   string

    Name string

}


type AlphaKey struct {

    Id     string

    Source string

}


r, err := buildResults("", reflect.TypeOf(AlphaKey{}))

fmt.Printf("%T %+v %v\n", r[0], r, err)


r, err = buildResults("", reflect.TypeOf(BetaKey{}))

fmt.Printf("%T %+v %v\n", r[0], r, err)

輸出:


main.AlphaKey [{Id:aa Source:asource} {Id:aa Source:asource} {Id:aa Source:asource}] <nil>

main.BetaKey [{Id:aa Name:aname} {Id:aa Name:aname} {Id:aa Name:aname}] <nil>

在Go Playground上嘗試一下。


筆記:


上面的解決方案將返回一個(gè)類型的值,[]interface{}其元素將是靜態(tài)類型,interface{}而它們的動(dòng)態(tài)類型將是reflect.Type參數(shù)指定的類型。因此,例如,如果您使用以下類型調(diào)用它:


bt := reflect.TypeOf(BetaKey{})

結(jié)果切片中的值將具有動(dòng)態(tài)類型,BetaKey因此您可以像這樣安全地鍵入斷言它們:


results, err := buildResults("some query", bt)

if err == nil {

    for _, v := range results {

        key := v.(BetaKey)

        // key is of type BetaKey, you may use it like so

    }

} else {

    // handle error

}


查看完整回答
反對(duì) 回復(fù) 2022-01-10
?
白豬掌柜的

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

我用 json 寫了一個(gè)小例子,而不是 sql 行。您可以嘗試從此代碼進(jìn)行開發(fā):


package main


import (

    "fmt"

    "reflect"

    "encoding/json"

)


type A struct {

    AField int `json:"a"`

}


type B struct {

    BField string `json:"b"`

}


func build(str string, typ reflect.Type) interface{} {

    results := reflect.MakeSlice(reflect.SliceOf(typ), 0, 10)

    for i:=0; i < 5; i++ {

        res := reflect.New(typ)

        json.Unmarshal([]byte(str), res.Interface())

        results = reflect.Append(results, res.Elem())

    }

    return results.Interface();

}


func main() {

    a := build("{ \"a\": 15 }", reflect.TypeOf(&A{}))

    fmt.Printf("%T : %V\n", a, a)

    b := build("{ \"b\": \"my string\" }", reflect.TypeOf(&B{}))

    fmt.Printf("%T : %V\n", b, b)

}


查看完整回答
反對(duì) 回復(fù) 2022-01-10
  • 2 回答
  • 0 關(guān)注
  • 145 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號(hào)

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