为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
浮云间 2022-08-01 17:06:57
我试图弄清楚确实提供了一个选项,以避免在开关分支中硬编码类型,而无需反射或运行时类型检查。这里的想法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 {    }谢谢
查看完整描述

1 回答

?
慕仙森

TA贡献1827条经验 获得超8个赞

假设您正在使用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)

请注意,如果您不打算重用语句,则无需手动准备语句。


查看完整回答
反对 回复 2022-08-01
  • 1 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信