猿问

类型检查,但不对类型进行硬编码或在数组中存储类型信息

我试图弄清楚确实提供了一个选项,以避免在开关分支中硬编码类型,而无需反射或运行时类型检查。


这里的想法GetGeneric不应该知道它收到的类型。调用方告诉 GetGeneric 使用类型 X,GetGeneric 传递给 stmt。获取填充模型数据。


在 stmt 下面的代码中。获取要求和类型为具体类型。下面是一个小示例。但我真的不喜欢我需要每个模型的硬编码类型作为单独的案例分支,这违背了整个目的,并且我被限制在stmt的接口上。获取报价。


func (pdb *PersistentDb) GetGeneric(ctx context.Context, sqlStmt string,

    model interface{}, args ...interface{}) (interface{}, error) {


    if pdb == nil {

        return nil, fmt.Errorf("you need to initilize persistent db first")

    }


    db, err := pdb.connectx(ctx)

    if err != nil {

        callistolog.Errorf("Failed connect to database error: %v", err)

        return nil, err

    }

    defer db.Close()


    stmt, errPrepare := db.Preparex(sqlStmt)

    if errPrepare != nil {

        callistolog.Errorf("Failed prepare sql statement error: %v", errPrepare)

        return nil, errPrepare

    }

    defer stmt.Close()


    switch t := model.(type) {

    case models.Role:

        err = stmt.Get(&t, args...)

        return t, err

    case models.Tenants:

        err = stmt.Get(&t, args...)

        return t, err

    // here for each models.Type I need add branch

    default:

        callistolog.Errorf("got unknown type")

    }


    return model, fmt.Errorf("unknown type")

}

一个选项是通过反射进行运行时检查,但我在想,我是否可以以某种方式声明类型的数组/切片,并优化开关分支到if分支,并在循环中迭代。


类似的东西(伪代码)


如果在模型数组中键入 T。将 T 作为泛型,并使其成为具体类型,T_hat T_hat地址传递给 stmt。获取


在某些语言中,您可以有一个 Object[] 等数组,并且可以检查对象类型。


在此示例中,调用方提供一个模型作为泛型接口,并在 GetGeneric 模型内部提供类型,如果该类型在已知类型的数组中,并且如果它不成为具体类型,则 stmt 将类型检查为具体类型。Get 接受这一点。


例如


如何在切片中存储类型信息而不是值,然后调度到 stmt。Get(&t, args...)


    types := []interface{} {model, model1, model2}

    for _,v := range types {


    }

谢谢


浮云间
浏览 118回答 1
1回答

慕仙森

假设您正在使用sqlx添加另一个反射层是没有意义的,而是使用它,因为它是被设计用来使用的。func (pdb *PersistentDb) GetGeneric(ctx context.Context, sqlStmt string, model interface{}, args ...interface{}) error {    if pdb == nil {        return fmt.Errorf("you need to initilize persistent db first")    }    db, err := pdb.connectx(ctx)    if err != nil {        callistolog.Errorf("Failed connect to database error: %v", err)        return err    }    defer db.Close()    stmt, errPrepare := db.Preparex(sqlStmt)    if errPrepare != nil {        callistolog.Errorf("Failed prepare sql statement error: %v", errPrepare)        return errPrepare    }    defer stmt.Close()    if err := stmt.Get(model, args...)        callistolog.Error(err)        return err    }    return nil}role := models.Role{}if err := pdb.GetGeneric(ctx, "select ...", &role, args...); err != nil {    return err}fmt.Println(role)// ...tentants := models.Tenants{}if err := pdb.GetGeneric(ctx, "select ...", &tenants, args...); err != nil {    return err}fmt.Println(tentants)请注意,如果您不打算重用语句,则无需手动准备语句。
随时随地看视频慕课网APP

相关分类

Go
我要回答